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

AcApProfileManager Класс

Имеется только один объект Profile Manager в сессию AutoCAD. ObjectARX обеспечивает глобальную функцию, чтобы получить доступ к этому объекту Profile Manager, названному acProfileManagerPtr(). Эта функция возвращает указатель на объект AcApProfileManager, который методы могут тогда быть вызваны.
AcApProfileManager класс обеспечивает контейнер для операций, обеспеченных окном Profiles. Не имеется никакого метода, обеспеченного, чтобы получить текущее имя профиля, так как это сохранено в переменной системы по имени CPROFILE и может быть получено, используя запрос к acutGetVar ().
AcApProfileManager класс обеспечивает следующие возможности

Возможности
Связанный Метод
Отыщите путь системного реестра для указанного профили
AcApProfileManager:: ProfileRegistryKey
Отыщите названия профилей которые в настоящее время существуют для конфигурации пользователя
AcApProfileManager:: ProfileListNames
Экспортируйте данный профиль в файл профили системного реестра AutoCAD (.arg) в формате REGEDIT4
AcApProfileManager:: ProfileExport
Импортируйте файл профили системного реестра AutoCAD (.arg) в данный профиль
AcApProfileManager:: ProfileImport
Удалите указанный профиль из системного реестра
AcApProfileManager:: ProfileDelete
Сбросьте указанный профиль к настройкам по умолчанию AutoCAD
AcApProfileManager:: ProfileReset
Делайте указанный профиль активным или текущим для сессии AutoCAD
AcApProfileManager:: ProfileSetCurrent
Копируйте существующий профиль к новому профилю
AcApProfileManager:: ProfileCopy
Переименуйте существующий профиль
AcApProfileManager:: ProfileRename
Добавьте новый объект реактора профиля
AcApProfileManager:: addReactor
Удалите существующий объект реактора профиля
AcApProfileManager:: removeReactor


AcApProfileManagerReactor Класс

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


Уведомление

Связанный Метод

Текущий профиль собирается быть измененным

 AcApProfileManagerReactor::currentProfileWillChange

Текущий профиль был изменен

 AcApProfileManagerReactor::currentProfileChanged

Текущий профиль собирается быть сброшенным

 AcApProfileManagerReactor::currentProfileWillBeReset

Текущий профиль был сброшен

 AcApProfileManagerReactor::currentProfileReset

Не-текущий профиль собирается быть сброшенным

 AcApProfileManagerReactor::profileWillReset

Не-текущий профиль был сброшен

AcApProfileManagerReactor:: profileReset

Пример менеджера профилей
Следующая выборка демонстрирует использование Классов AcApProfileManagerReactor и AcApProfileManager:
// Определить класс, полученный из AcApProfileManagerReactor, чтобы управлять уведомлениями.
//
class AsdkProfileManagerReactor : public AcApProfileManagerReactor
{
public:
void currentProfileWillChange(const char *newProfile);
void currentProfileChanged(const char *newProfile);
void currentProfileWillBeReset(const char *curProfile);
void currentProfileReset(const char *curProfile);
void profileWillReset(const char *profName);
void profileReset(const char *proName);
};
// Define the notification functions.
//
void
AsdkProfileManagerReactor::
currentProfileWillChange(const char *newProfile)
{
acutPrintf("\nCurrent profile will change: %s", newProfile);
}
void
AsdkProfileManagerReactor::
currentProfileChanged(const char *newProfile)
{
acutPrintf("\nCurrent profile changed: %s", newProfile);
}
void
AsdkProfileManagerReactor::
currentProfileWillBeReset(const char *curProfile)
{
acutPrintf("\nCurrent profile will be reset: %s", curProfile);
}
void
AsdkProfileManagerReactor::

currentProfileReset(const char *curProfile)

{

acutPrintf("\ nCurrent profile has been reset: %s", curProfile);

}

void

AsdkProfileManagerReactor::

profileWillReset(const char *profName)

{

acutPrintf("\nNon-current profile will be reset: %s", profName);

}

void

AsdkProfileManagerReactor::

profileReset(const char *profName)

{

acutPrintf("\nNon-current profile has been reset:%s", profName);

}

void

aFunction()

{

acutPrintf("This is AsdkProfileSample Test Application...\n");

// Attach the reactor for the duration of this command. Normally

// this would be added upon application initialization.

//

AsdkProfileManagerReactor *pProfileRector =

new AsdkProfileManagerReactor();

acProfileManagerPtr()->addReactor(pProfileRector);

// Obtain the path for the registry keys and print it out.

//

char *pstrKey;

acProfileManagerPtr()->ProfileRegistryKey(pstrKey, NULL);

if (pstrKey != NULL) {

acutPrintf("\nThe profiles registry key is: %s", pstrKey);

acutDelString(pstrKey);

}

// Get the list of all profiles in the user’s configuration

// and print them out.

//

AcApProfileNameArray arrNameList;

int nProfiles =

acProfileManagerPtr()->ProfileListNames(arrNameList);

acutPrintf("\nNumber of profiles currently "

"in the user profile list is: %d", nProfiles);

for (int i = 0; i < nProfiles; i++)

acutPrintf("\nProfile name is: %s", arrNameList[i]);

// Copy the unnamed profile to the AsdkTestProfile.

//

acProfileManagerPtr()->ProfileCopy(

"AsdkTestProfile",

"<>",

"This is a test");

// Reset the newly copied profile to AutoCAD defaults.

//

acProfileManagerPtr()->ProfileReset("AsdkTestProfile");

// Make this new profile current.

//

acProfileManagerPtr()->ProfileSetCurrent("AsdkTestProfile");

// Change a value in the profile. For this example, make the

// cursor big.

//

struct resbuf rbCursorSize;

rbCursorSize.restype = RTSHORT;

rbCursorSize.resval.rint = 100;

acedSetVar("CURSORSIZE", &rbCursorSize);

// Rename the profile to a new name.

//

acProfileManagerPtr()->ProfileRename(

"AsdkTestProfile2",

"AsdkTestProfile",

"This is another test");

// Export the profile.

//

acProfileManagerPtr()->ProfileExport(

"AsdkTestProfile2",

"./AsdkTestProfile2.arg");

// Import the profile.

//

acProfileManagerPtr()->ProfileImport(

"AsdkTestProfile3",

"./AsdkTestProfile2.arg",

"This is a copy of AsdkTestProfile2"

"by Exporting/Importing",

Adesk::kTrue);

// Remove the reactor.

//

acProfileManagerPtr()->removeReactor(pProfileRector);

}

AcAxOleLinkManager

AcAxOleLinkManager используется, чтобы управлять связью от объекта резидента базы до его объекта COM. Это сделано,  прикрепляя переходный реактор к AcDbObject. Переходный реактор имеет одну переменную, содержащую IUNKNOWN объекта COM. Этот переходный реактор также используется, чтобы вызвать IACADBASEOBJECT:: OnModified () когда AcDbObject изменяется.
Получить указатель на OLE связывают менеджера, используют AcAxGetOleLinkManager (). AcAxOleLinkManager класс описан ниже:
// AcAxOleLinkManager
используется, чтобы поддержать связь между объектами ARX и их соответствующей оберткой COM.
//
class AcAxOleLinkManager
{
public:
// Учитывая указатель на объект резидента базы, возвратите IUNKNOWN
//  обертки COM. NULL возвращен, если никакая обертка не найдена.
//
virtual IUnknown* GetIUnknown(AcDbObject* pObject) = 0;
// Установить связь между объектом резидента базы и оберткой COM.
//  Если IUNKNOWN
- NULL, то связь удалена.
//
virtual Adesk::Boolean SetIUnknown(AcDbObject* pObject, IUnknown* pUnknown) = 0;
// Учитывая указатель на объект базы данных, возвратите IUNKNOWN
// обертки COM. NULL возвращен, если никакая обертка не найдена.
//
virtual IUnknown* GetIUnknown(AcDbDatabase* pDatabase) = 0;
// Установить связь между объектом базы данных и оберткой COM.
// Если IUNKNOWN
- NULL, то связь удалена.
//
virtual Adesk::Boolean SetIUnknown(AcDbDatabase* pDatabase,
IUnknown* pUnknown) = 0;
// Учитывая указатель на объект базы данных, возвратите IDISPATCH объекта документа.
// NULL возвращен, если база данных не принадлежит специфическому документу.
//
virtual IDispatch* GetDocIDispatch(AcDbDatabase* pDatabase)= 0;
// Установить связь между объектом базы данных и IDISPATCH
документа, которому
// это принадлежит. Если IDISPATCH
- NULL, то связь удалена.
//
virtual Adesk::Boolean SetDocIDispatch(AcDbDatabase* pDatabase,
IDispatch* pDispatch) = 0;
};

AcDb Библиотека

AcDb библиотека обеспечивает классы, которые составляют базу данных AutoCAD.
Эта база данных сохраняет всю информацию для графических объектов, называемых
Объекты, которые составляют рисунок AutoCAD, также как неграфический Объект (например, уровни, linetypes, и текстовые стили) которые являются также частью рисунка. Вы можете сделать запрос и управлять существующими образцами Объектов AutoCAD и объекты библиотеки AcDb,  Вами могут создавать новые образцы из объектов базы данных.
База данных AutoCAD содержит эти главные элементы:
·
набор девяти таблиц идентификаторов, которые имеют уникально названный входом таблицы идентификаторов Объектов. Эти объекты представляют различный обычно используемый AcDbDatabase Объекты и компоненты данных.
· словарь названий объектов (класса AcDbDictionary), который обеспечивает “Оглавление” для рисунка AutoCAD. Первоначально, эта таблица содержания содержит ИДЕНТИФИКАТОРЫ из четырех других словарей, используемых в соответствии с AutoCAD.Приложения, которые Вы разрабатываете, однако, являются свободными прибавить другие объекты Словарей.
· фиксированный набор приблизительно 200 переменных заголовка, чей значения установлены AutoCAD.
Иерархия классов для AcDb библиотеки следующие:
AcRxObject

AcDbDictionary
   AcDbDictionaryWithDefault
AcDbFilter
   AcDbLayerFilter
    AcDbSpatialFilter
AcDbGroup
AcDbIDBuffer
AcDbIndex
    AcDbLayerIndex
    AcDbSpatialIndex
AcDbLongTransaction
AcDbMlineStyle
AcDbPlaceholder
AcDbPlotSettings
    AcDbLayout
AcDbProxyObject
AcDbXrecord
AcDbEntity
AcDbRasterImageDef
AcDbRasterImageDefReactor
AcDbRasterVariables
AcDbSymbolTable
     AcDbAbstractViewTable
           AcDbViewportTable
           AcDbViewTable
AcDbBlockTable
AcDbDimStyleTable
AcDbFontTable
AcDbLayerTable
AcDbLinetypeTable
AcDbRegAppTable
AcDbTextStyleTable
AcDbUCSTable
AcDbSymbolTableRecord
      AcDbAbstractViewTableRecord
             AcDbViewportTableRecord
             AcDbViewTableRecord
AcDbBlockTableRecord
AcDbDimStyleTableRecord
AcDbFontTableRecord
AcDbLayerTableRecord
AcDbLinetypeTableRecord
AcDbRegAppTableRecord
AcDbTextStyleTableRecord
AcDbUCSTableRecord


Для получения дополнительной информации на AcDb библиотеке, см. главу 2, “ Учебник для начинающих Базы данных, ” глава 4, “ Операции Базы данных, ” глава 5, “ Объекты(цели) Базы данных, ” глава 6, “Объекты”, и глава 7, “ Контейнерные Объекты(цели). ” Для информации относительно получения новых классов от AcDbObject и AcDbEntity, см. главу 12, “ Происходящий от AcDbObject ” и главу 13, “ Происходящий от AcDbEntity. ”

AcDbCompositeFilteredBlockIterator Класс

AcDbCompositeFilteredBlockIterator класс обеспечивает замену к нормальной блочной итерации. Обеспечивая список фильтра в init () метод, объект
AcDbCompositeFilteredBlockIterator ищет передачу
AcDbIndex полученные объекты через
AcDbFilter:: indexClass () метод, и создает объекты
AcDbFilteredBlockIterator. Если совпадение
-to-date indexClass () объекты не доступны, это создает
AcDbFilteredBlockIterator через AcDbFilter:: newIterator () метод. Это тогда заказывает композицию объектов
AcDbFilteredBlockIterator, основанных на
AcDbFilteredBlockIterator:: estimatedHits () и
AcDbFilteredBlockIterator::buffersForComposition () методы. Коллекция фильтров - конъюнкция условий{*состояний*}. Это означает, что объект ID выводится от iterator только, если бы вводы () метод каждого фильтра приняли бы объект ID.

AcDbCurve: Функции к Перегрузке

Класс пользователя должен перегрузить следующие функции:
virtual Adesk::Boolean
isClosed() const;
virtual Adesk::Boolean
isPeriodic() const;
virtual Adesk::Boolean
isPlanar() const;
virtual Acad::ErrorStatus
getPlane(AcGePlane&, AcDb::Planarity&) const;
virtual Acad::ErrorStatus
getStartParam(double&) const;
virtual Acad::ErrorStatus
getEndParam(double&) const;
virtual Acad::ErrorStatus
getStartPoint(AcGePoint3d&) const;
virtual Acad::ErrorStatus
getEndPoint(AcGePoint3d&) const;
virtual Acad::ErrorStatus
getPointAtParam(double, AcGePoint3d&) const;
virtual Acad::ErrorStatus
getParamAtPoint(const AcGePoint3d&, double&)const;
virtual Acad::ErrorStatus
getDistAtParam(double param, double& dist) const;
virtual Acad::ErrorStatus
getParamAtDist(double dist, double& param) const;
virtual Acad::ErrorStatus
getDistAtPoint(const AcGePoint3d&, double&) const;
virtual Acad::ErrorStatus
getPointAtDist(double, AcGePoint3d&) const;
virtual Acad::ErrorStatus
getFirstDeriv(
double param,
AcGeVector3d& firstDeriv) const;
virtual Acad::ErrorStatus
getFirstDeriv(
const AcGePoint3d&,
AcGeVector3d& firstDeriv) const;
virtual Acad::ErrorStatus
getSecondDeriv(
double param,
AcGeVector3d& secDeriv) const;
virtual Acad::ErrorStatus
getSecondDeriv(
const AcGePoint3d&,
AcGeVector3d& secDeriv) const;
virtual Acad::ErrorStatus
getClosestPointTo(
const AcGePoint3d& givenPnt,
AcGePoint3d& pointOnCurve,
Adesk::Boolean extend
= Adesk::kFalse) const;
virtual Acad::ErrorStatus
getClosestPointTo(
const AcGePoint3d& givenPnt,
const AcGeVector3d& normal,
AcGePoint3d& pointOnCurve,
Adesk::Boolean extend
= Adesk::kFalse) const;
virtual Acad::ErrorStatus
getOrthoProjectedCurve(
const AcGePlane&,

AcDbCurve*& projCrv) const;

virtual Acad::ErrorStatus

getProjectedCurve(

const AcGePlane&,

const AcGeVector3d& projDir,

AcDbCurve*& projCrv) const;

virtual Acad::ErrorStatus

getOffsetCurves(

double offsetDist,

AcDbVoidPtrArray& offsetCurves) const;

virtual Acad::ErrorStatus

getSpline(AcDbSpline*& spline) const;

virtual Acad::ErrorStatus

getSplitCurves(

const AcGeDoubleArray& params,

AcDbVoidPtrArray& curveSegments) const;

virtual Acad::ErrorStatus

getSplitCurves(

const AcGePoint3dArray& points,

AcDbVoidPtrArray& curveSegments) const;

virtual Acad::ErrorStatus

extend(double newParam);

virtual Acad::ErrorStatus

extend(

Adesk::Boolean extendStart,

const AcGePoint3d& toPoint);

virtual Acad::ErrorStatus

getArea(double&) const;

AcDbDatabase:: wblockCloneObjects () Функция

WblockCloneObjects () функция - элемент AcDbDatase. Это будет глубоко имитировать объекты от одной базы данных до другой и следовать за жесткими ссылками{*справочниками*} так, чтобы все зависимые объекты также имитировались. Поведение отчетов{*записей*} таблицы идентификаторов, когда дубликаты найдены, определено параметром типа. Следующая диаграмма показывает отношениям между типом таблицы идентификаторов (перечисление DuplicateRecordCloning) и глубокий тип аналога (перечисление DeepCloneType).
Отношения между DeepCloneTypes и DuplicateRecordCloning для Различные команды и функции

Command or API Function
DeepCloneType
DuplicateRecordCloning
COPY
kDcCopy
kDrcNotApplicable
EXPLODE
kDcExplode
kDrcNotApplicable
BLOCK
kDcBlock
kDrcNotApplicable
INSERT/BIND
kDcXrefInsert
kDrcIgnore
XRESOLVE
kDcSymTableMerge
kDrcXrefMangleName
INSERT
kDcInsert
kDrcIgnore
insert()
kDcInsertCopy
kDrcIgnore
WBLOCK
kDcWblock
kDrcNotApplicable
deepCloneObjects()
kDcObjects
kDrcNotApplicable
wblockObjects()
kDcObjects
kDrcIgnore
wblockObjects()
kDcObjects
kDrcReplace
wblockObjects()
kDcObjects
kDrcMangleName
wblockObjects()
kDcObjects
kDrcUnmangleName

Пример
длинной транзакции

Эти простые показы примера, как проверять объекты от другой базы данных, измените их в текущей базе данных, и затем проверьте{*отметьте*} их назад в к первоначальной базе данных. Запросы, которые являются частью длинного операционного процесса,  обозначены в полужирной печати.
void
refEditApiExample()
{
AcDbObjectId transId;
AcDbDatabase* pDb;
char *fname;
struct resbuf *rb;
// Get a dwg file from the user.
//
rb = acutNewRb(RTSTR);
acedGetFileD("Pick a drawing", NULL, "dwg", 0, rb);
fname = (char*)acad_malloc(strlen(rb->resval.rstring) + 1);
strcpy(fname, rb->resval.rstring);
acutRelRb(rb);
// Open the dwg file.

//

pDb = new AcDbDatabase(Adesk::kFalse);

pDb->readDwgFile(fname);

// Get the block table and then the model space record.

//

AcDbBlockTable *pBlockTable;

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

AcDbBlockTableRecord *pOtherMsBtr;

pBlockTable->getAt(ACDB_MODEL_SPACE, pOtherMsBtr,

AcDb::kForRead);

pBlockTable->close();

// Create an iterator

//

AcDbBlockTableRecordIterator *pIter;

pOtherMsBtr->newIterator(pIter);

// Set up an object ID array.

//

AcDbObjectIdArray objIdArray;

// Iterate over the model space BTR. Look specifically

// for Lines and append their object ID to the array.

//

for (pIter->start(); !pIter->done(); pIter->step()) {

AcDbEntity *pEntity;

pIter->getEntity(pEntity, AcDb::kForRead);

// Look for only AcDbLine objects and add them to the

// objectId array.

//

if (pEntity->isKindOf(AcDbLine::desc())) {

objIdArray.append(pEntity->objectId());

}

pEntity->close();

}

delete pIter;

pOtherMsBtr->close();

// Now get the current database and the object ID for the

// current database’s model space BTR.

//

AcDbBlockTable *pThisBlockTable;

acdbHostApplicationServices()->workingDatabase()

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

AcDbBlockTableRecord *pThisMsBtr;

pThisBlockTable->getAt(ACDB_MODEL_SPACE, pThisMsBtr,

AcDb::kForWrite);

pThisBlockTable->close();

AcDbObjectId id = pThisMsBtr->objectId();

pThisMsBtr->close();

// Create the long transaction. This will check all the entities

// out of the external database.

acapLongTransactionManagerPtr()->checkOut(transId,

objIdArray, id);

// Now modify the color of these entities.

//

int colorIndex;

acedGetInt("\nEnter color number to change entities to: ",

&colorIndex);

AcDbObject* pObj;

if (acdbOpenObject(pObj, transId, AcDb::kForRead) == Acad::eOk)

{

// Get a pointer to the transaction

//

AcDbLongTransaction* pLongTrans =

AcDbLongTransaction::cast(pObj);

if (pLongTrans != NULL) {


// Get a work set iterator

//

AcDbLongTransWorkSetIterator* pWorkSetIter =

pLongTrans->newWorkSetIterator();

// Iterate over the entities in the work set

// and change the color.

for (pWorkSetIter->start(); !pWorkSetIter->done(); pWorkSetIter->step()) {

AcDbEntity *pEntity;

acdbOpenAcDbEntity(pEntity, pWorkSetIter->objectId(),

AcDb::kForWrite);

pEntity->setColorIndex(colorIndex);

pEntity->close();

}

delete pWorkSetIter;

}

pObj->close();

}

// Pause just to see the change.

//

char str[132];

acedGetString(0, "\nNote the new colors. Press return to \

check the objects back in to the original database", str);

// Check the entities back in to the orginal database.

//

acapLongTransactionManagerPtr()->checkIn(transId);

// Save the original database, since we made changes

//

pDb->saveAs(fname);

// Close and Delete the database.

//

delete pDb;

pDb = NULL;

acad_free(fname);

}

AcDbDatabaseSummaryInfo Класс

AcDbDatabaseSummaryInfo класс формирует набор символьных строк, которые могут использоваться, чтобы прибавить дополнительную информацию к DWG файлу. Максимальная длина этих строк - 511 символов. Эта информация сохранена и восстановлена{*отыскана*} в объекте Summary Information с определенными методами для каждого информационного поля. Предопределенные поля
  • N Заголовок

  • N Тема

  • N Автор

  • N Ключевые слова

  • N Комментарии

  • N Последний{*прошлый*} сохраненный

  • N номер Пересмотра

  • N ядро Гиперсвязи

  • Вы можете создавать ваши собственные заказные поля в дополнение к предопределенным полям.
    Эти заказные поля сохранены в списке, и Вы можете управлять заказными полями или их названием{*именем*} (или клавиша{*ключ*}) или позиция (индекс) в списке. Заказные поля индексированы, начинаясь в 1, и не имеется никакого предела числу полей, которые Вы можете создавать.

    AcDbEntity функции, обычно перегружаемые

    Следующие функции обычно перегружаются при наследовании класса пользователя от AcDbEntity. Действительно ли Вы перегружаете эти функции, зависит от заказных функциональных возможностей, которые ваш класс поддерживает.
    virtual void
    viewportDraw(AcGiViewportDraw* mode);
    virtual void
    list() const;
    virtual Acad::ErrorStatus
    intersectWith(
    const AcDbEntity* ent,
    AcDb::Intersect intType,
    AcGePoint3dArray& points,
    int thisGsMarker = 0,
    int otherGsMarker = 0) const;
    virtual Acad::ErrorStatus
    intersectWith(
    const AcDbEntity* ent,
    AcDb::Intersect intType,
    const AcGePlane& projPlane,
    AcGePoint3dArray& points,
    int thisGsMarker = 0,
    int otherGsMarker = 0) const;
    virtual Acad::ErrorStatus
    getOsnapPoints(
    AcDb::OsnapMode osnapMode,
    int gsSelectionMark,
    const AcGePoint3d& pickPoint,
    const AcGePoint3d& lastPoint,
    const AcGeMatrix3d& viewXform,
    AcGePoint3dArray& snapPoints,
    AcDbIntArray& geomIds) const;
    virtual Acad::ErrorStatus
    getStretchPoints( AcGePoint3dArray&) const;
    virtual Acad::ErrorStatus
    moveStretchPointsAt(
    const AcDbIntArray& indices,
    const AcGeVector3d& offset);
    virtual Acad::ErrorStatus
    explode( AcDbVoidPtrArray& entitySet) const;
    virtual Acad::ErrorStatus
    getSubentPathsAtGsMarker(
    AcDb::SubentType type,
    int gsMark,
    const AcGePoint3d& pickPoint,
    const AcGeMatrix3d& viewXform,
    int& numPaths,
    AcDbFullSubentPath* & subentPaths,
    int numInserts = 0,
    AcDbObjectId* entAndInsertStack = NULL) const;
    virtual Acad::ErrorStatus
    applyPartialUndo(
    AcDbDwgFiler* undoFiler,
    AcRxClass* classObj);
    virtual void
    subSetDatabaseDefaults( AcDbDatabase* pDb);
    virtual void
    saveAs( AcGiWorldDraw* mode, AcDb::SaveType st);

    AcDbEntity Функции, редко перегружаемые

    Следующие функции AcDbEntity редко перегружаются:
    virtual Acad::ErrorStatus
    setColor( const AcCmColor &color);
    virtual Acad::ErrorStatus
    setColorIndex( Adesk::UInt16 color);
    virtual Acad::ErrorStatus
    setLinetype( const char* newVal);
    virtual Acad::ErrorStatus
    setLinetype( AcDbObjectId newVal);
    virtual void
    getEcs( AcGeMatrix3d& retVal) const;
    virtual Acad::ErrorStatus
    getGsMarkersAtSubentPath(
    const AcDbFullSubentPath& subPath,
    AcDbIntArray& gsMarkers) const;
    virtual Acad::ErrorStatus
    highlight( const AcDbFullSubentPath& subId = kNullSubent) const;
    virtual Acad::ErrorStatus
    unhighlight( const AcDbFullSubentPath& subId = kNullSubent) const;
    virtual AcDbEntity*
    subentPtr( const AcDbFullSubentPath& id) const;
    virtual Adesk::Boolean
    saveImagesByDefault() const;
    virtual void
    setAttributes( AcGiSubEntityTraits* pTraits);
    Следующие разделы обсуждают перегрузку нескольких обычно используемых функций.

    AcDbEntity перегружаемые функции

    Следующие функции должны быть перегружены, когда Вы получаете класс пользователя из AcDbEntity:
    virtual Adesk::Boolean
    worldDraw(AcGiWorldDraw* mode);
    virtual Acad::ErrorStatus
    getGeomExtents(AcDbExtents& extents) const;
    virtual Acad::ErrorStatus
    transformBy(const AcGeMatrix3d& xform);
    virtual Acad::ErrorStatus
    getTransformedCopy(const AcGeMatrix3d& xform,AcDbEntity*& ent) const;
    virtual Acad::ErrorStatus
    getGripPoints(AcGePoint3dArray& gripPoints, AcDbIntArray& osnapModes, AcDbIntArray& geomIds) const;
    virtual Acad::ErrorStatus
    moveGripPointsAt( const AcDbIntArray& indices, const AcGeVector3d& offset);

    AcDbObject: Функции Часто Перегружаемые

    Класс пользователя часто отменяет следующие функции:
    virtual Acad::ErrorStatus
    audit(AcDbAuditInfo*);
    // Commonly useful, as this happens at a point where a new
    // object state is being committed.
    //
    virtual Acad::ErrorStatus subClose();
    // The next two functions apply to container objects.
    //
    virtual Acad::ErrorStatus
    deepClone(AcDbObject* pOwnerObject,
    AcDbObject*& pClonedObject,
    AcDbIdMapping& idMap,
    Adesk::Boolean isPrimary = Adesk::kTrue) const;
    virtual Acad::ErrorStatus
    wblockClone(AcRxObject* pOwnerObject,
    AcDbObject*& pClonedObject,
    AcDbIdMapping& idMap,
    Adesk::Boolean isPrimary = Adesk::kTrue) const;

    AcDbObject: Функции Иногда Перегружаемые

    Класс пользователя иногда отменяет следующие функции:
    virtual Acad::ErrorStatus
    subErase(Adesk::Boolean erasing);
    virtual Acad::ErrorStatus
    subHandOverTo(AcDbObject* newObject);
    virtual Acad::ErrorStatus
    subOpen(AcDb::OpenMode);
    virtual Acad::ErrorStatus
    subCancel();
    virtual Acad::ErrorStatus
    subSwapIdWith(AcDbObjectId otherId,
    Adesk::Boolean swapXdata = Adesk::kFalse);

    AcDbObject: Функции Редко Перегружаемые

    Класс пользователя редко отменяет следующие функции:
    virtual Acad::ErrorStatus
    setOwnerId(AcDbObjectId);
    virtual resbuf*
    xData(const char* regappName = NULL) const;
    virtual Acad::ErrorStatus
    setXData(const resbuf* xdata);
    virtual void
    addPersistentReactor(AcDbObjectId objId);
    virtual Acad::ErrorStatus
    removePersistentReactor(AcDbObjectId objId);
    virtual void cancelled(const AcDbObject* dbObj);
    virtual void copied(const AcDbObject* dbObj, const AcDbObject* newObj);
    virtual void erased(const AcDbObject* dbObj, Adesk::Boolean pErasing = Adesk::kTrue);
    virtual void goodbye(const AcDbObject* dbObj);
    virtual void openedForModify(const AcDbObject* dbObj);
    virtual void modified(const AcDbObject* dbObj);
    virtual void modifyUndone(const AcDbObject* dbObj);
    virtual void modifiedXData(const AcDbObject* dbObj);
    virtual void unappended(const AcDbObject* dbObj);
    virtual void objectClosed(const AcDbObjectId objId);
    virtual void modifiedGraphics(const AcDbEntity* dbEnt);

    AcDbObject и События Уведомления Базы данных

    Когда Вы получаете стертый () уведомление на объекте базы данных, объект отмечено как стерто, но - все еще часть базы данных. Когда Вы получаете недобавленный в конец () уведомление, объект было отмечено недобавленным в конец и - не часть базы данных, если это не повторно добавлено в конец. До свидания () уведомление на объекте послано непосредственно перед тем, как это уходит полностью. Эти сигналы уведомления, что объект собирается быть удаленным из базы данных и удален от памяти.
    Вы можете хотеть удалить ваш реактор из объекта, когда Вы получаете стертый () или недобавленный в конец () уведомление. Однако, если Вы удаляете реактор в этой точке, Вы не будете получать повторно добавленный в конец () или нестертый () уведомление для того объекта. Чтобы контролировать эти события, используйте эквивалентные уведомления на базе данных, не только объект:
    AcDbDatabaseReactor::objectErased()
    AcDbDatabaseReactor::objectUnappended()
    AcDbDatabaseReactor::objectReappended()

    AcDbObject: необходимые функции для перегрузки

    Заказной класс должен перегрузить следующие функции:
    virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* filer);
    virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* filer) const;
    virtual Acad::ErrorStatus dxfInFields(AcDbDxfFiler* filer);
    virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler* filer) const;


    AcEd Библиотека

    AcEd библиотека обеспечивает классы для определения и регистрации новых команд AutoCAD, которые работают как встроенные команды. Новые команды, которые Вы определяете,  упомянуты как “родные” команды, потому что они постоянно находятся в той же самой внутренней структуре (AcEdCommandStack) как встроенные команды. AcEd библиотека также обеспечивает редактора реактором и набором из глобальных функций для взаимодействия с AutoCAD. Важный класс в этом библиотеке - AcEditorReactor; это контролирует состояние редактора AutoCAD и уведомляет приложение, когда указанные события происходят, типа старта, окончания или команды отмены.
    Иерархия классов для AcEd библиотеки следующие:
    AcRxObject
    AcEdCommand
    AcEdCommandStack
    AcEdUlContext
    AcEdJlg
    AcEdInputPointFilter
    AcEdInputPointMonitor
    AcEdInputPointMeneger
    AcEdSolidSubEntitySelector
    AcTransaction
    AcDbTransactionMeneger
    AcTransactionMeneger
    Для информации относительно регистрации новых команд AutoCAD, использующих ObjectARX, cм. главу 3, “ ObjectARX Прикладные Основы. ” Для примера использования
    Редактор реактор, см. главу 15, “Уведомление”.

    AcEditorReactor Класс

    Следующие AcEditorReactor уведомления имеют силу в ObjectDBX:
  • dwgFileOpened

  • databaseToBeDestroyed

  • saveComplete

  • beginInsert

  • otherInsert

  • abortInsert

  • endInsert

  • wblockNotice

  • beginWblock

  • otherWblock

  • endWblock

  • beginDeepClone

  • beginDeepCloneXlation

  • abortDeepClone

  • endDeepClone

  • sysVarChanged

  • sysVarWillChange


  • AcGe Библиотека

    AcGe библиотека используется AcDb библиотекой и обеспечивает сервисные классы типа векторов и матриц, которые используются, чтобы исполнить общие двумерные и трехмерные геометрические операции. Это также обеспечивает основные геометрические объекты типа точек, кривых, и поверхностей.
    AcGe библиотека состоит из двух главных подмножеств: классы для двумерной геометрии и классов для трехмерной геометрии. Главные абстрактные классы - AcGeEntity2d и AcGeEntity3d. Несколько основных классов, не полученные из любого другого класса включают AcGePoint2d, AcGeVector2d, и AcGeMatrix2d (показанный в начале иерархии классов). Эти основные классы могут использоваться, чтобы исполнить много типов общих(обычных) операций, типа добавления вектора к точке, вычисление точки или векторного произведения двух векторов, и вычисления программы двух матриц. Классы с  более высоким уровнем этой библиотеки осуществлены, используя thesebasic классы. Иерархия классов для AcGe библиотеки следующие:

    AcGeEntity2D
    AcGeBoundBlock2d
    AcGeClipBoundary2d
    AcGeCurve2d
           AcGeCircArc2d
           AcGeCompositeCurve2d
           AcGeEllipArc2d
           AcGeExternalCurve2d
           AcGeLinearEnt2d
                  AcGeLine2d
                  AcGeLineSeg2d
                  AcGeRay2d
           AcGeOffsetCurve2d
           AcGeSplineEnt2d
                   AcGeCubicSplineCurve2d
                   AcGeNurbCurve2d
                   AcGePolyline2d
    AcGeCurveCurveInt2d
    AcGePointEnt2d
           AcGePointOnCurve2d
           AcGePosition2d

    AcGeCurveBoundary
    AcGe
    AcGeContext
    AcGeDwgIO
    AcGeDxfIO
    AcGeFileIO
    AcGeFiler
    AcGeInterval
    AcGeKnotVector
    AcGeLibVersion
    AcGeMatrix2d
    AcGeMatrix3d
    AcGePoint2d
         AcAxPoint2d
    AcGePoint3d
           AcAxPoint3d
    AcGeScale2d
    AcGeScale3d
    AcGeTol
    AcGeVector2d
    AcGeVector3d
    AcGeEntity2D

    AcGeBoundBlock3d
    AcGeCurve3d
            AcGeCircArc3de
            AcGeCompositeCurve3d
            AcGeEllipArc3e
            AcGeExternalCurve3d
            AcGeLinearEnt3d
                    AcGeLine3d
                    AcGeLineSeg3d
                    AcGeRay3d
                    AcGeMatrix3d
            AcGeOffsetCurve3d
            AcGeSplineEnt3d
                    AcGeCubicSplineCurve3d
                    AcGeNurbCurve3d
                    AcGePolyline3d
                             AcGeAugPolyline3d
    AcGeCurveCurveInt3d
    AcGeCurveSurfInt
    AcGePointEnt3d
             AcGePointOnCurve3d
             AcGePointOnSurface
             AcGePosition3d
    AcGeSurfSurfInt
    AcGeSurface
            AcGeCone
            AcGeCylinder
            AcGeExternalBoundedSurface
            AcGeExternalSurface
            AcGeNurbSurface
            AcGeOffsetSurface
            AcGePlanarEnt
                    AcGeBoundedPlanet
                    AcGePlane
            AcGeSphere
            AcGeTorus




    AcGe библиотека обеспечивает несколько различных систем координат. Для получения дополнительной информации, см. главу 27, “ Использование Библиотеки Геометрии. ” Выборка программ этого справочника иллюстрирует многочисленные обычные использования классов AcGe.

    AcGe Примеры Постоянства

    Следующее - пример чтения и записи AcGeExternalSurface с конкретным подклассом AcGeFiler. С целью этого примера, регистратор преобразования в последовательную форму - DWG регистратор. Следовательно, это обеспечивает постоянство,  читая и пишущий формат DWG:
    #include "gefiler.h"
    class AcDbDwgFiler;
    class AcGeDwgFiler : public AcGeFiler
    {
    public:
    // Construct the filer with DWG filer.
    // All read and write methods are implemented
    // by delegating to this filer.
    AcGeDwgFiler (AcDbDwgFiler* = NULL);
    // Read/write methods.
    //
    Acad::ErrorStatus readBoolean(Adesk::Boolean*);
    Acad::ErrorStatus writeBoolean(Adesk::Boolean);
    Acad::ErrorStatus readBool(bool*);
    Acad::ErrorStatus writeBool(bool);
    Acad::ErrorStatus readChar(char*);
    Acad::ErrorStatus writeChar(char);
    Acad::ErrorStatus readShort(short*);
    Acad::ErrorStatus writeShort(short);
    Acad::ErrorStatus readLong(long*);
    Acad::ErrorStatus writeLong(long);
    Acad::ErrorStatus readUChar(unsigned char*);
    Acad::ErrorStatus writeUChar(unsigned char);
    Acad::ErrorStatus readUShort(unsigned short*);
    Acad::ErrorStatus writeUShort(unsigned short);
    Acad::ErrorStatus readULong(unsigned long*);
    Acad::ErrorStatus writeULong(unsigned long);
    Acad::ErrorStatus readDouble(double*);
    Acad::ErrorStatus writeDouble(double);
    Acad::ErrorStatus readPoint2d(AcGePoint2d*);
    Acad::ErrorStatus writePoint2d(const AcGePoint2d&);
    Acad::ErrorStatus readPoint3d(AcGePoint3d*);
    Acad::ErrorStatus writePoint3d(const AcGePoint3d&);
    Acad::ErrorStatus readVector2d(AcGeVector2d*);
    Acad::ErrorStatus writeVector2d(const AcGeVector2d&);
    Acad::ErrorStatus readVector3d(AcGeVector3d*);
    Acad::ErrorStatus writeVector3d(const AcGeVector3d&);
    // Set/Get methods
    //
    AcGeDwgFiler& setDwgFiler (AcDbDwgFiler*);
    AcDbDwgFiler* dwgFiler ();
    protected:
    AcDbDwgFiler* mpFiler;
    };
    // Inline methods.
    //
    inline
    AcGeDwgFiler::AcGeDwgFiler(AcDbDwgFiler* filer) : mpFiler(filer)
    {}
    inline AcGeDwgFiler&
    AcGeDwgFiler::setDwgFiler(AcDbDwgFiler* filer)

    {

    mpFiler = filer;

    return *this;

    }

    inline AcDbDwgFiler*

    AcGeDwgFiler::dwgFiler()

    {

    return mpFiler;

    }

    Следующий фрагмент кода иллюстрирует выполнение нескольких функций.

    Другие функции осуществлены тем же самым способом:

    Acad::ErrorStatus AcGeDwgFiler::readBoolean(Adesk::Boolean* data)

    {

    return mpFiler ? mpFiler->readBoolean(data) : Acad::eNoDatabase;

    }

    Acad::ErrorStatus AcGeDwgFiler::writeBoolean(Adesk::Boolean data)

    {

    return mpFiler ?

    mpFiler->writeBoolean(data) : Acad::eNoDatabase;

    }

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

    class AcGeExternalCurve2d;

    class AcGeExternalCurve3d;

    class AcGeExternalBoundedSurface;

    class AcGeExternalSurface;

    class AcGePersistentXEnt : public AcDbObject

    {

    public:

    ACRX_DECLARE_MEMBERS (AcGePersistentXEnt);

    AcGePersistentXEnt ();

    ~AcGePersistentXEnt ();

    Acad::ErrorStatus dwgOutFields (AcDbDwgFiler*) const;

    Acad::ErrorStatus dwgInFields (AcDbDwgFiler*);

    AcGeExternalSurface* mpXSrf;

    };

    Реализация этого класса следующая:

    ACRX_DXF_DEFINE_MEMBERS(

    AcGePersistentXEnt, AcDbObject, 0,

    GEPERSISTENT, "GeometryLib");

    Acad::ErrorStatus

    AcGePersistentXEnt::dwgOutFields(AcDbDwgFiler* filer) const

    {

    assertReadEnabled();

    Acad::ErrorStatus stat = AcDbObject::dwgOutFields(filer);

    if (stat != Acad::eOk)

    {

    ADS_ASSERT(0);

    return stat;

    }

    // Only interested in a file filer.

    //

    if (filer->filerType() != AcDb::kFileFiler)

    return stat;

    AcGeDwgFiler geDwgFiler(filer);

    stat = AcGeFileIO::outFields(

    &geDwgFiler,

    AcGe::gLibVersion);

    if ((stat = AcGeFileIO::outFields(&geDwgFiler, *mpXSrf)) != Acad::eOk)

    return stat;

    return stat;

    }

    Acad::ErrorStatus

    AcGePersistentXEnt::dwgInFields(AcDbDwgFiler* filer)

    {

    assertWriteEnabled();

    Acad::ErrorStatus stat = AcDbObject::dwgInFields(filer);

    if (stat != Acad::eOk)

    {

    ADS_ASSERT(0);

    return stat;

    }

    // Only interested in a file filer.

    //

    if (filer->filerType() != AcDb::kFileFiler)

    return stat;

    AcGeDwgFiler geDwgFiler(filer);

    AcGeLibVersion gelibVersion;

    if ((stat = AcGeFileIO::inFields(&geDwgFiler, gelibVersion)) != Acad::eOk)

    return stat;

    acutPrintf("\n... Reading External Surface\n");

    mpXSrf = new AcGeExternalSurface;

    ADS_ASSERT(mpXSrf);

    if ((stat = AcGeFileIO::inFields(&geDwgFiler, *mpXSrf, gelibVersion)) != Acad::eOk)

    return stat;

    return stat;

    }

    AcGi Библиотека

    AcGi библиотека обеспечивает графический интерфейс, используемый для рисунка объектов AutoCAD. Эта библиотека используется AcDbEntity функциями элемента
    WorldDraw (), viewportDraw (), и saveAs (), вся часть стандартного протокола объекта. WorldDraw () функция должен быть определен всеми заказными классами объекта. Объект AcGiWorldDraw обеспечивает API, через который AcDbEntity:: worldDraw () может производить его графическое представление во всех областях просмотра одновременно. Точно так же объект(цель) AcGiViewportDraw обеспечивает API, через который AcDbEntity:: viewportDraw () функция может про-ducedifferent графические представления для каждой области просмотра.
    Иерархия классов для AcGi библиотеки следующие:
    AcRxObject
    AcGiCommonDraw
    AcGiWorldDraw
    AcGiWorldDraw
    AcGiContext
    AcGiEdgeData
    AcGiFaceData
    AcGiGeometry
    AcGiViewportGeometry
    AcGiWorldGeometry
    AcGiLinetypeEngine
    AcGiSubEntityTraits
    AcGiDrawableTraits
    AcGiTextStyle
    AcGiVertexData
    AcGiViewport
    AcGiDrawable
    AcGiGlyph
    Для получения дополнительной информации при использовании AcGi классы, см. главу 13, “ Происходящий от AcDbEntity. ”

    AcGi Краткий обзор

    AcGi библиотека определяет набор интерфейсов, с которыми объекты могут выполнять себя к основной системе графики. Эта глава обсуждает, как AcGi работает в среде AutoCAD. Однако, это работает подобным способом для других систем, которые осуществляют интерфейсы AcGi.
    AcGi библиотека позволяет примитивам сделать запрос для информации относительно процесса регенерации, и детализировать набор примитивов, использующих классы геометрии.
    Обратитесь к AcGi, происходит в пределах следующего три функции члена базового класса AcGiDrawable:
    Adesk::Boolean
    worldDraw( AcGiWorldDraw*);
    void
    viewportDraw( AcGiViewportDraw*);
    Adesk::UInt32
    setAttributes( AcGiDrawableTraits*);
    AcDbEntity наследует эти функции от AcGiDrawable. Как правило, при осуществлении заказного примитива, Вы перегрузите эти функции и обеспечите ваше собственное выполнение.
    Когда AutoCAD должен восстановить графику, чтобы отобразить примитив, это вызывает эти функции следующим способом:
    AcGiDrawable *pDrawable;
    pDrawable->setAttributes(pDt);
    if (!pDrawable->worldDraw(pWd))
    {
    for each viewport
    pDrawable->viewportDraw(pVd);
    }
    Для заказных примитивов, AutoCAD вызывает ваш setAttributes (), worldDraw (), и viewportDraw () функциями, если Вы перегрузили их. AutoCAD проходит в соответствующих объектах AcGi к этим функциям. Это позволило бы AutoCAD отобразить ваш заказной примитив, также, как если это был встроенный примитив.
    SetAttributes() функция инициализирует атрибуты для примитива, типа цвета, уровня, и linetype. WorldDraw () функция формирует часть из графического представления примитива, которое может быть определено независимым от любого специфического вида пространства модели или контекстов области просмотра пространства листа. ViewportDraw () функция тогда формирует часть иждивенца представления из графики примитива. Если любая из графики примитива - иждивенец представления, worldDraw () должен возвратить kFalse, и viewportDraw () должен быть осуществлен.
    Наоборот, если примитив не имеет никакой графики иждивенца представления, то worldDraw () должен возвратить kTrue, и заказной примитив не осуществляет viewportDraw ().

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

    AcGi Краткий обзор

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

    Иерархия классов для AcGi следующая:

    AcGi Краткий обзор

    Базовый класс AcGiCommonDraw формирует общие функциональные возможности AcGiViewportDraw и AcGiWorldDraw. Базовый класс AcGiGeometry формирует общие функциональные возможности AcGiViewportGeometry и AcGiWorldGeometry. Эти базовые классы позволяют Вам записывать большее количество общего кода, который может обрабатывать оба случая, если желательно.

    AcGi

    AcGi API - интерфейс между AcDb и системы исполнения имели обыкновение отображать AcDb модели. Этот интерфейс используется функциями члена AcDbEntity worldDraw (), viewportDraw (), и saveAs (), которые являются частью стандартного протокола примитива.
    Один метод создания приложения, способного к основному рассмотрению должен осуществить полностью AcGi API. Получите ваши собственные классы выполнения из классов AcGi, типа AcGiWorldDraw и AcGiWorldGeometry. Чтобы рисовать данный примитив, вызовите его worldDraw () функцией, затем пройдите в указателе на образец вашего AcGiWorldDraw-полученного класса. Вы тогда получите повторные вызовы в различных членов вашего класса. Функции члена - графические примитивы типа круга () и ломаной линии () функции. Их будут пропускать все необходимые параметры, необходимые, чтобы рисовать их. AcGi должен быть осуществлен ведущим приложением, желающим, чтобы использовать определенный графический символ, выполняющий логику, определенную примитивами. Преимущество использования AcGi состоит в том, что приложение главного компьютера не должно знать что - нибудь относительно того, как примитив предназначен, чтобы быть представленным вне установленного набора геометрических примитивов и графических черт, типа цвета, linetype, и текстового шрифта. AutoCAD имеет его собственное внутреннее выполнение AcGi, в то время как AcGix библиотека снабжала ObjectDBX, сломает многое из комплекса, выполняющего логику, указанную AcGi в относительно простой набор графических примитивов.
    Некоторые методы AcGiWorldDraw - для целей запроса (deviation() и numberOfIsolines ()) и могут использоваться примитивом, чтобы определить степень, к которой различные примитивы будут “ мозаичны; ” другими словами, насколько “плотный” линии, составляющие сферу (например) были бы.
    AcGiWorldDraw:: regenType () метод может использоваться, чтобы сообщить AcGi,является ли перегенеральный запрос для каркасов или лиц с нормалями. Например, это - от acgi.h file:
    // Они - текущие виды режимов регенерации области просмотра.
    // Этот режим не может быть установлен пользователем, но этом можно делать запрос в случае, если Вы должны брать различные действия для различных режимов регенерации.
    //
    //
    typedef enum {
    eAcGiRegenTypeInvalid = 0,
    kAcGiStandardDisplay = 2,
    kAcGiHideOrShadeCommand,
    kAcGiRenderCommand,
    kAcGiSaveWorldDrawForR12
    } AcGiRegenType;
    ОБРАТИТЕ ВНИМАНИЕ Для примеров использования интерфейса AcGi, см. типовой модуль в samples/common/myacgi.*.

    AcGix

    Эта библиотека - двигатель, который разбивает AcGi-определенную геометрию и черты в маленький, простой набор графических примитивов, определенных в соответствии с протоколом класса AcGixVectorTaker. Это работает на зарегистрированном наборе областей просмотра, для которых приложение должно обеспечить выполнение AcGixVectorTaker и AcGiViewport. AcGix делает запрос снабженного AcGiViewport для параметров регенерации и транслирует AcGi примитивы, в которые это получает от примитивов,  вызывает к снабженному vectortaker. AcGix не делает никакую интерпретацию из того, как снабженные приложением области просмотра фактически отображены. Это - до выполнения AcGixVectorTaker.
    Чтобы использовать AcGix с заказной графической системой скорее чем использование SimpleView, Вы должны снабдить ваши собственные выполнение Классов AcGiViewport и AcGixVectorTaker. Фактические образцы области просмотра и vectortaker могут быть разделены между множественными областями просмотра, если это имеет смысл для вашего приложения.
    Принимается, что vectortaker выполнение исполнит отсечение необходимого примитивов против степеней области просмотра. AcGix библиотека снабжена в двоичной форме с набором файлов заголовка API.
    Следующие файлы заголовка содержат исходное определение AcGix API:
    § include/acgix.h
    § include/acgixcontext.h
    § include/acgixstd.h
    § include/acgixutilities.h
    § include/acgixvectortaker.h
    § include/acgixviewportset.h
    § include/acgixviewportmanager.h
    AcGix клиенты связываются с release/AcGix.lib, который связывает приложение с release/AcGix.dll.

    AcRx Библиотека

    AcRx библиотека обеспечивает классы с  системным уровнем для DLL инициализации и соединения и для регистрации класса во время выполнения и идентификации. Базовый класс этой библиотеки - AcRxObject, который обеспечивает следующие средства:
    · идентификация класса во время выполнения и анализу наследования
    · добавление во время выполнения нового протокола к существующему классу (см. главу 19,“Расширение Протокола”)
    · объектное равенство и испытание сравнения
    · копирование объекта
    AcRx библиотека также обеспечивает набор макрокоманд C++, чтобы помочь Вам создать новые ObjectARX классы, полученные из AcRxObject (см. главу 11, «Получение
    заказного ObjectARX класса»).
    AcRxDictionary - другой важный класс в этой библиотеке. Словарь - a
    Отображение от текстовой строки до другого объекта(цели). AcRx библиотека размещает ее объекты, классы, и сервисные словари в глобальном объектном словаре, который
    является образцом AcRxDictionary класса. Приложения могут прибавлять объекты к
    этому словарю так, чтобы они были  доступны для других приложений.
    Иерархия классов для AcRx библиотеки следующие:
    AcRxObject
    AcRxClass
    AcRxDictionary
    AcRxDynamicLinker
    AcRxEvent
    AcEditor
    AcRxService
    AcRxKernal
    AcDbServices
    AcEdServices
    AcadAppInfo

    AcrxEntryPoint () Функция

    ObjectARX-приложение не имеет главного, потому что это - DLL. Также, приложение не вызывает ads_init (), ads_abort (), и ads_link (). Программист ADS осуществляет функцию acrxEntryPoint () со следующей сигнатурой:
    extern "C"
    AcRx::AppRetCode
    acrxEntryPoint(AcRx::AppMsgCode msg, void* appId);
    Первый параметр, компонент данных AcRx класса вызвал сообщение, представляет сообщение, посланное от ObjectARX ядра до приложения.
    Второй параметр - непрозрачная метка к данным, пропускал к блокировке и разблокировать функции для приложения. Функция возвращает код состояния, типа RSRSLT или RSERR.
    AutoCAD вызывает в ObjectARX модуль acrxEntryPoint () чтобы передать сообщения к приложению. Все запросы, чтобы вызвать функции через acedDefun () сделаны acrxEntryPoint (), упрощая перемещение программ ADS к среде программы ObjectARX.
    ObjectARX-приложения отвечают на значение компонента данных AcRx класса AppMsgCode скорее чем к возвращаемому значению ads_link (), ads_exit (), и ads_abort ().

    AcRxObject: Функции Редко Перегружаемые

    Класс пользователя редко отменяет эти функции:
    virtual AcRxObject*
    clone() const;
    virtual void
    copyFrom(const AcRxObject* pSrc);
    // Do not override; AcDbObject behavior is already accounted for.
    //
    virtual HRESULT __stdcall
    QueryInterface (    REFIID riid,
    void ** ppvObject );
    virtual ULONG __stdcall
    AddRef();
    virtual ULONG __stdcall
    Release();

    AcUi Диалоговые классы

    Диалоговые классы AcUi формируют на диалоговые классы AdUi и пригодны для использования только с AutoCAD.
    CAcUiDialog Класс
    CAcUiDialog - класс общего назначения, который обеспечивает набор функций члена, учитывающих диалоги изменяемого размера и постоянство данных в AutoCAD.
    CAcUiTabMainDialog
    Класс

    CAcUiTabMainDialog представляет основной контейнерный диалог в AutoCAD табулированный диалог. CAcUiTabMainDialog и CACUITABMAINDIALOG используются на месте CPROPERTYSHEET и CPROPERTYPAGE, чтобы создать табулированные диалоги в AutoCAD.
    CAcUiTabChildDialog
    Класс

    CAcUiTabChildDialog представляет позицию табуляции в табулированном диалоге.
    CAcUiTabMainDialog и CACUITABCHILDDIALOG используются на месте CPROPERTYSHEET и CPROPERTYPAGE, чтобы создать табулированные диалоги в AutoCAD. Каждая позиция табуляции в AutoCAD табулировала диалог - CACUITABCHILDDIALOG.
    CAcUiAlertDialog
    Класс

    CAdUiAlertDialog представляет аварийный диалог с тремя кнопками. Одна кнопка - кнопка CANCEL, и другие два текста командной кнопки установлены программистом. Это - аварийный диалог общего назначения.
    CAcUiFileDialog Класс
    CAcUiFileDialog обеспечивает Определенное автохамом образование из CADUIFILEDIALOG.

    AcUi Классы Кнопки

    Это средство управления формирует на классы AdUi и пригодно для использования только с AutoCAD.
    CAcUiPickButton Класс
    CAcUiPickButton специализирует CACUIBITMAPBUTTON, который является оберткой для класса CAdUiBitmapButton. CAcUiPickButton обеспечивает кнопку, которая отображает стандартный точечный рисунок кнопки указки.
    CAcUiSelectButton
    Класс

    CAcUiSelectButton специализирует CACUIPICKBUTTON. Это обеспечивает кнопку, которая отображает стандартный точечный рисунок кнопки выбора.

    AcUi MRU Поля со списком

    AcUi расширяет{*продлевает*} поддержку поля со списком, чтобы управлять MRU (наиболее недавно используемый) список автоматически в пределах управления. Основные функциональные возможности обеспечиваются классом CAcUiMRUComboBox (полученный из CACUICOMBOBOX). Класс компаньона, CAcUiMRUListBox, обеспечивает поддержку DrawTip для combo поля ComboLBox. Это необходимо из-за MRU выполнения поля со списком как владелец - тянущееся управление.
    Пять специализировался, MRU классы поля со списком также обеспечиваются: CAcUiArrowHeadComboBox, CAcUiColorComboBox, CAcUiLineWeightComboBox, CAcUiPlotStyleTablesComboBox, и CACUIPLOTSTYLENAMESCOMBOBOX. Они обеспечивают стандартные интерфейсы пользователя для управления dimensioning стрелками - указателями, цветными и lineweight выборами, и составляют график таблицы стиля и составляют график стиля, называет выбор.
    CAcUiMRUComboBox
    Класс

    CAcUiMRUComboBox наследует CACUICOMBOBOX и служит, поскольку базовый класс для владелец - тянет поля со списком, которые осуществляют список MRU. Каждый элемент{*пункт*} в списке может содержать маленькое изображение{*образ*}, сопровождаемое некоторым текстом. Каждый элемент{*пункт*} также прослеживает уникальное значение, упомянутое как груз, и поддерживаемый как стандартный Windows ® ITEMDATA в пределах управления. Класс показывает встроенную поддержку для до двух универсальных, необязательных элементов{*пунктов*}, упомянутых как Option1 и Option2. Они обычно соответствуют{*переписываются*} “ByLayer” и “ByBlock” и часто имеют специальное значение.
    Два других элемента{*пункта*}, Other1 и Other2, можно также допускать и появляться только, когда список понижен вниз. Выбор любого из этих элементов{*пунктов*} вызывает специальный случай в пределах управления.
    CAcUiArrowHeadComboBox
    Класс

    CAcUiArrowHeadComboBox специализирует CACUIMRUCOMBOBOX для dimensioning выбора стрелки - указателя. Управление отображает точечные рисунки, представляющие стандарт AutoCAD dimensioning стили стрелки - указателя, которые являются всегда подарком{*настоящим*} в списке. По умолчанию никакие необязательные или дополнительные элементы{*пункты*} не присутствуют или добавленный. Груз, связанный с каждым элементом{*пунктом*} - индекс AutoCAD для связанной готовой стрелки - указателя. Когда MRU элементы{*пункты*} добавлены к списку, они автоматически назначены уникальное грузовое значение (который будет больший чем индекс AutoCAD для определяемого пользователем стиля стрелки - указателя).

    CAcUiColorComboBox

    Класс


    CAcUiColorComboBox специализирует CACUIMRUCOMBOBOX для цветного выбора. Образчики цветов дисплея управления, представляющие выборы от палитры AutoCAD.

    Готовые элементы{*пункты*} всегда представляют в управлении, отражают номера цвета 1 до 7. Оба необязательных элемента{*пункта*} используются; Option1 отображает “ByLayer”, и Option2 отображает “ByBlock”. MRU дисплей элементов{*пунктов*} “ Окрашивают nnn, ”, где nnn - связанный номер цвета. Груз, связанный с каждым элементом{*пунктом*} указывает, что номер цвета AutoCAD (типа от 1 до 255), “ByBlock” касается 0, и “ByLayer” соответствует 256. Other1 элемент{*пункт*} допускается и вызывает диалог Выбора Цвета AutoCAD. Если Other2 допускают, это отображает как “ Windows ... ” и по умолчанию вызывает Выбор Цвета Windows Общий{*обычный*} диалог. Если пользователь выбирает элемент{*пункт*} от любого из этих диалогов,  выбор появляется в списке MRU и становится текущим элементом{*пунктом*} в управлении.

    CAcUiLineWeightComboBox

    Класс


    CAcUiLineWeightComboBox специализирует CACUIMRUCOMBOBOX для lineweight выбора. Управление отображает маленький предварительный просмотр lineweights AutoCAD, поддерживает, в пределах от 0.05mm к 2.11mm, и не включает “Ни один” и произвольно “Значение по умолчанию”. И показатель и имперские значения отображены, в зависимости от установки LWUNITS системной переменной. Оба необязательных элемента{*пункта*} используются; Option1 отображает “ByLayer”, и Option2 отображает “ByBlock”. Каждый элемент{*пункт*} обслуживает{*поддерживает*} груз, который передает AcDb элемента{*пункта*}:: kLnWtxxx значение.

    CAcUiPlotStyleTablesComboBox

    Класс


    CAcUiPlotStyleTablesComboBox специализирует CACUIMRUCOMBOBOX для графического выбора таблицы стиля. Управление отображает графические названия{*имена*} таблицы стиля согласно текущему графическому режиму стиля (цветное - зависимый режим или названные графические стили). MRU функциональные возможности поля со списком не используются. Точечный рисунок, указывающий внедренную адресную таблицу отображен в названном графическом режиме стиля для тех таблиц, которые имеют внедренную адресную таблицу.

    CAcUiPlotStyleNamesComboBox

    Класс


    CAcUiPlotStyleNamesComboBox специализирует CACUIMRUCOMBOBOX для графического выбора имени стиля. MRU функциональные возможности combo не используются, и “ByLayer”, “ByBlock”, и “ Другой ... ” элементы{*пункты*} может быть условно отображен. Если подарок{*настоящее*}, “ Другой ... ” элемент{*пункт*} может вызывать или Назначающийся Графический диалог Стиля, или Поток Набора Составляет график диалога Стиля.

    CAcUiMRUListBox Класс

    CAcUiMRUListBox происходит от CACUILISTBOX. Я t я s, используемый CACUIMRUCOMBOBOX, чтобы подклассифицировать список управления (ComboLBox) и обеспечиваю поддержку DrawTip.

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

    AdUi Диалоговые классы

    Диалоговые классы AdUi пригодны для использования в приложениях других чем AutoCAD.
    CAdUiBaseDialog Класс
    CAdUiBaseDialog обеспечивает основную поддержку для окон совета{*предупреждения*} (ToolTips и TextTips) и AdUi системы обработки сообщения. Это также поддерживает контекстную справку и справку F1 в диалогах. Это - общий{*обычный*} базовый класс для всех диалогов кроме, те базировались на общем{*обычном*} диалоге файла.
    CAdUiDialog Класс
    CAdUiDialog - универсальный класс, который обеспечивает набор функций члена, учитывающих диалоги изменяемого размера и постоянство данных.
    CAdUiFileDialog
    CAdUiFileDialog специализирует CFILEDIALOG аналогичный путь, поскольку CAdUiBaseDialog специализирует CDIALOG. Класс обеспечивает основную поддержку для окон совета{*предупреждения*} (ToolTips и TextTips), контекстной справки и AdUi обработки сообщения в общем{*обычном*} диалоге файла. В отличие от CADUIBASEDIALOG, не имеется никакой встроенной поддержки для постоянства размера и позиции.
    CAdUiTabMainDialog
    Класс

    CAdUiTabMainDialog представляет основной контейнерный диалог в табулированном диалоге.
    CAdUiTabMainDialog и CADUITABMAINDIALOG используются на месте CPROPERTYSHEET и CPROPERTYPAGE, чтобы создать табулированные диалоги.
    CAdUiTabChildDialog
    Класс

    CAdUiTabChildDialog представляет позицию табуляции в табулированном диалоге.
    CAdUiTabMainDialog и CADUITABCHILDDIALOG используются на месте CPROPERTYSHEET и CPROPERTYPAGE, чтобы создать табулированные диалоги. Каждая позиция табуляции в табулированном диалоге - CADUITABCHILDDIALOG.

    AdUi и AcUi Классы Строки управления

    Следующие классы обеспечивают поддержку для состыковывающихся окон.
    CAdUiDockControlBar
    Класс

    CADUIDOCKCONTROLBAR класс, часть системы стыковки, добавляет расширенные{*продленные*} возможности к MFC CControlBar класс. Основная особенность, обеспеченная - изменение размеров строк управления когда состыковано{*закреплено*}. Больше чем одна строка управления можно закреплять вместе, каждый из них являющийся способным быть измененными, индивидуально используя расщепители, созданные системой стыковки. CAdUiDockControlBar также идет с областью механизма захвата и близкой кнопкой когда состыковано{*закреплено*}. Управляйте состоянием областей, может переключаться состыкованным{*закрепленным*} с несостыкованным{*незакрепленным*} или наоборот, дважды нажимая на механизме захвата когда состыковано{*закреплено*}, или области заголовка когда несостыковано{*незакреплено*}, или,  перемещая их с мышью. Система стыковки обрабатывает постоянство строк управления, сохранение их позиция и состояние поперек сеансов. Наконец, CAdUiDockControlBar обеспечивает заданное по умолчанию контекстное меню, чтобы управлять поведением области, с возможностью для разработчика, чтобы настроить это меню.
    CAcUiDockControlBar
    Класс

    CACUIDOCKCONTROLBAR класс добавляет к CADUIDOCKCONTROLBAR, классифицируют поведение, обычное к AutoCAD dockable инструментальные средства: когда пользователь перемещает курсор мыши из области{*региона*} строки управления, фокус автоматически отдается обратно к AutoCAD.

    AdUi и AcUi Средства редактирования

    Следующие классы обеспечивают специализированное средство управления редактирования, включая поддержку для определенных типов данных.
    CAdUiEdit Класс
    CAdUiEdit получен из CEDIT класса, чтобы обеспечить средство управления окна редактирования. Этот класс обеспечивает поддержку для окон совета{*предупреждения*} за обрезанные текстовые элементы{*пункты*} (TextTips).
    Этот класс берет разрядные флажки, чтобы добавить желательное поведение проверки правильности, основанное на следующих типах ввода: Числовой, Строковый, Угловой, и названия{*имена*} Символа. Вообще Вы должны использовать один из классов, полученных из Определенного автохамом класса CAcUiComboBox, который добавляет определенную проверку правильности типа данных и постоянство к управлению. Они - CACUISTRINGEDIT, CAcUiSymbolEdit, CAcUiNumericEdit, и
    CACUIANGLEEDIT.
    CAcUiEdit Класс
    CAcUiEdit обеспечивает Определенное автохамом образование из CADUIEDIT.
    CAcUiAngleEdit Класс
    CAcUiAngleEdit получен из CACUIEDIT и обеспечивает специализированный конструктор, чтобы гарантировать, что бит стиля AC_ES_ANGLE всегда устанавливается в маске стиля. Объекты этого класса предназначены для использования в редактировании угловых / вращательных данных, определенных к параметрам настройки AutoCAD.
    CAcUiNumericEdit
    Класс

    CAcUiNumericEdit получен из CACUIEDIT и обеспечивает специализированный конструктор, чтобы гарантировать, что бит стиля AC_ES_NUMERIC всегда устанавливается в маске стиля. Объекты этого класса предназначены для использования в редактировании числовых данных (типа расстояния) определенный к параметрам настройки AutoCAD.
    CAcUiStringEdit Класс
    CAcUiStringEdit получен из CACUIEDIT и обеспечивает специализированный конструктор, чтобы гарантировать, что бит стиля AC_ES_STRING всегда устанавливается в маске стиля. Любой ввод приемлем.
    CAcUiSymbolEdit Класс
    CAcUiSymbolEdit получен из CACUIEDIT и обеспечивает специализированный конструктор, чтобы гарантировать, что бит стиля AC_ES_SYMBOL всегда устанавливается в маске стиля. Объекты этого класса предназначены для использования в редактировании правильных{*допустимых*} названий{*имен*} символа AutoCAD.

    CAdUiListBox Класс

    CAdUiListBox специализирует MFC CListBox, чтобы обеспечить управление, которое поддерживает AdUi передачу сообщений. Класс может использоваться, где-нибудь CLISTBOX может использоваться. Так как это обеспечивает дополнительную контейнерно - побочную поддержку для AdUi зарегистрированными сообщениями, удобно использовать CADUIBASEDIALOG (или полученный класс) с CADUILISTBOX (или полученный класс) средство управления.

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

    CAdUiListCtrl Класс

    CAdUiListCtrl получен из CLISTCTRL класса, чтобы обеспечить средство управления списка. Этот класс обеспечивает поддержку для окон совета{*предупреждения*} за обрезанные текстовые элементы{*пункты*} (TextTips).

    TextTips будет появляться за обрезанные элементы{*пункты*} заголовка для средства управления списка в представлении{*виде*} сообщения, и для индивидуума обрезанные текстовые элементы{*пункты*} в столбцах в теле управления списка. Нарисованное пользователем средство управления поддержано.

    CAdUiHeaderCtrl

    CAdUiHeaderCtrl специализирует CHEADERCTRL. Наиболее часто, CAdUiHeaderCtrl представляет подклассифицируемый заголовок, содержащийся в управлении списка (CAdUiListCtrl).

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

    AdUi и AcUi Средство управления Поля со списком

    Следующие классы обеспечивают поддержку для средства управления поля со списком.
    CAdUiComboBox Класс
    CAdUiComboBox получен из CCOMBOBOX класса, чтобы обеспечить средство управления поля со списком. Этот класс обеспечивает поддержку для окон совета{*предупреждения*} за обрезанные текстовые элементы{*пункты*} (TextTips), и проверку правильности данных в средствах редактирования. Этот класс берет разрядные флажки, чтобы добавить желательное поведение проверки правильности, основанное на следующих типах ввода: числовой, строковый, угловой, и названия{*имена*} символа. Вообще, Вы должны использовать один из классов, полученных из Определенного автохамом класса CAcUiComboBox, который добавляет определенную проверку правильности типа данных и постоянство к управлению. Они - CACUISTRINGCOMBOBOX, CAcUiSymbolComboBox, CAcUiNumericComboBox, и
    CACUIANGLECOMBOBOX. В поддержку для нарисованного пользователем средства управления также встраивают.
    CAcUiAngleComboBox
    Класс

    CACUIANGLECOMBOBOX конструктор автоматически создает CACUIANGLEEDIT, чтобы подклассифицировать окно редактирования управления. Это учитывает проверку правильности углов, определенных к параметрам настройки AutoCAD.
    CAcUiNumericComboBox
    Класс

    CACUIANGLECOMBOBOX конструктор автоматически создает CACUINUMERICEDIT, чтобы подклассифицировать окно редактирования управления. Это учитывает проверку правильности чисел{*номеров*}, определенных к параметрам настройки AutoCAD.
    CAcUiStringComboBox
    Класс

    CACUISTRINGCOMBOBOX конструктор автоматически создает CACUISTRINGEDIT, чтобы подклассифицировать окно редактирования управления. Любой ввод приемлем.
    CAcUiSymbolComboBox
    Класс

    CACUISYMBOLCOMBOBOX конструктор автоматически создает CACUISYMBOLEDIT, чтобы подклассифицировать окно редактирования управления. Правильные{*допустимые*} названия{*имена*} символа AutoCAD - приемлемый ввод.

    AdUi Классы Кнопки

    Это средство управления пригодно для использования в приложениях других чем AutoCAD.
    CAdUiOwnerDrawButton
    Класс

    Этот класс обеспечивает основным, владелец - тянут кнопку. Класс может использоваться, где-нибудь CBUTTON может использоваться. Когда используется в AdUi-полученном диалоге (или класс, который поддерживает, AdUi передача сообщений) CAdUiOwnerDrawButton автоматически обеспечивает для дисплея AdUi окна совета{*предупреждения*}. Класс также поддерживает, перетащат и опустить, Статический и Дисплей Инструмента, и эффекты PointedAt. В Режиме визуального отображения Инструмента, кнопка кажется плоской и выскочит когда направлено в (типа того, когда мышь перемещается поверх кнопки). Щелчок кнопки заставит это поместить вниз.
    В Статическом Режиме визуального отображения, кнопка кажется плоской и ведет себя скорее статический элемент управления чем кнопка команды. Комбинация предоставления перетащит и опустить, и Статический Дисплей соответствующий созданию узлов, которые получают файлы через, перетащат и опустить.
    CAdUiBitmapButton
    Класс

    Этот класс специализирует CADUIOWNERDRAWBUTTON, чтобы обеспечить кнопку, которая отображает точечный рисунок (изображение{*образ*} оттянуто очевидно в кнопке). По умолчанию, объекты этого класса автоматически изменяют размеры, чтобы приспособить связанное растровое изображение. В отличие от CBITMAPBUTTON MFC'S, только один точечный рисунок необходим, чтобы определить все государства кнопки (класс MFC'S требует четырех точечных рисунков).
    CAdUiBitmapStatic
    Класс

    CAdUiBitmapStatic специализирует CADUIBITMAPBUTTON, чтобы обеспечить кнопку, которая допускает Статическому Дисплею по умолчанию. Это средство управления действует скорее статика чем кнопки.
    CAdUiDropSite Класс
    CAdUiDropSite специализирует CADUIBITMAPSTATIC, чтобы обеспечить кнопку, которая допускает, перетащат и опустить также как Статический Дисплей. Это средство управления может получать файлы через, перетащат и опустить.
    CAdUiToolButton Класс
    CAdUiToolButton специализирует CADUIBITMAPBUTTON, чтобы обеспечить кнопку, которая допускает Дисплею Инструмента по умолчанию. Это средство управления появляется скорее кнопки инструментальной панели чем регулярные кнопки.

    AdUi Окна подсказок

    AdUi
    обеспечивает три типа окон совета{*предупреждения*}: ToolTips, TextTips, и DrawTips.
    ToolTips
    представляют готовый Windows ToolTips, как предусмотрено обычным Средством управления DLL установленный на системе пользователя. TextTips
    - основанные на тексте окна совета, которые выскочат по управлению, обычно показать данные, которые пользователь был бы иначе должен листать в представление. DrawTips – расширение TextTips.
    Управление ниже совета обычно ответствено за закрашивание содержания совета (аналогичное владельцу - тянущемуся совету).
    Большинство приложений редко вовлекает эти классы непосредственно, так как AdUi
    обычно обрабатывает все требования. AdUi использует его внутреннюю систему передачи сообщений, чтобы вести переговоры между контейнерами и средством управления и решать когда и как отобразить совет.
    CAdUiTipWindow Класс
    CAdUiTipWindow - основной AdUi класс окна совета{*предупреждения*}. Эти объекты обрабатывают универсальный совет{*предупреждение*}, отображают и знают, когда автоматически скрыть себя (типа обнаружения движения курсора, краткой блокировки времени, или деятельности клавиатуры).
    CAdUiTextTip Класс
    CAdUiTextTip специализирует CADUITIPWINDOW, чтобы отобразить TextTip.
    CAdUiDrawTipText
    Класс

    CAdUiDrawTipText используется внутренне AdUi системой передачи сообщений, чтобы сообщить управлению, что окно совета{*предупреждения*} нуждается в перекрашивании. Управление имеет опцию изменения{*замены*} атрибутов контекста устройства окна совета{*предупреждения*} и рисунка текста.

    AdUi Расширяемость Позиции табуляции Поддержки Классов

    Следующие классы обеспечивают поддержку для диалогов позиции табуляции.
    CAdUiTabExtensionManager
    Класс

    CAdUiDialogManager - класс, который управляет добавлением и удалением позиций табуляции от табулированного диалога, который является расширяемым. Если диалог - расширяемая позиция табуляции, образец этого класса найден в CADUITABMAINDIALOG.
    CAdUiTab Класс
    CAdUiTab формирует MFC CTabCtrl и добавляет функциональные возможности к этому. Один из этих объектов найден в основном объекте диалога.

    Анонимные Блоки

    Вы можете создавать анонимные блоки,  вызывая acdbEntMake (). Чтобы делать так, Вы должны открыть блок с именем, чей первый символ - * и блочный флажок типа (группа 70) чей младший бит установлен в 1. AutoCAD назначает новый анонимный блок имя; символы в строке имени, которые следуют за *,  часто игнорируются. Вы тогда создаете анонимный блок,  путем Вы создали бы регулярный блок, за исключением того, что это более важно вызвать acedGetInput ().
    Поскольку имя сгенерировано в соответствии с AutoCAD, ваша программа не имеет никакого другого пути знания имени нового блока.
    Следующий код начинает анонимный блок, заканчивает его, и возвращает его имя.
    int status;
    struct resbuf *entlist;
    ads_point basept;
    char newblkname[20];
    ads_point pnt1 = ( 0.0, 0.0, 0.0);
    entlist = acutBuildList(
    RTDXF0, "BLOCK",
    2, "*ANON", // Only the ’*’ matters.
    10, "1", // No other flags are set.
    0 );
    if (entlist == NULL) {
    acdbFail("Unable to create result buffer list\n");
    return BAD;
    }
    status = acdbEntMake(entlist);
    acutRelRb(entlist); // Release acdbEntMake buffer.
    if (status != RTNORM) {
    acdbFail("Unable to start anonymous block\n");
    return BAD;
    }
    // Add entities to the block by more acdbEntMake calls.
    .
    .
    .
    entlist = acutBuildList(RTDXF0, "ENDBLK", 0 );
    if (entlist == NULL) {
    acdbFail("Unable to create result buffer list\n");
    return BAD;
    }
    status = acdbEntMake(entlist);
    acutRelRb(entlist); // Release acdbEntMake buffer.
    if (status != RTKWORD) {
    acdbFail("Unable to close anonymous block\n");
    return BAD;
    }
    status = acedGetInput(newblkname);
    if (status != RTNORM) {
    acdbFail("Anonymous block not created\n");
    return BAD;
    }
    К ссылке анонимный блок, создайте примитив вставки с acdbEntMake() (Вы не можете передавать анонимный блок к команде INSERT.)
    Продолжая предыдущий пример, следующий кодовый фрагмент вставляет анонимный блок в (0,0).
    basept[X] = basept[Y] = basept[Z] = 0.0;

    entlist = acutBuildList(

    RTDXF0, "INSERT",

    2, newblkname, // From acedGetInput

    10, basept,

    0 );

    if (entlist == NULL) {

    acdbFail(" Unable to create result buffer list\n");

    return BAD;

    }

    status = acdbEntMake(entlist);

    acutRelRb(entlist); // Release acdbEntMake buffer.

    if (status != RTNORM) {

    acdbFail("Unable to insert anonymous block\n");

    return BAD;

    }

    Функции Данных Примитива и Графический Экран

    Изменяется к рисунку, сделанному функциями данных примитива,  отражен на графическом экране, при условии, что удаляемый примитив, восстановлен, изменяется, или сделан, находится в области и находится на уровне, который является в настоящее время видимым. Имеется одно исключение: когда acdbEntMod() изменяет подпримитив, это не модифицирует изображение сложного примитива. Причина должна быть ясна. Если, например, приложение должно было изменить 100 вершин сложной ломаной линии с 100 выполняемый с помощью итераций, вызывает acdbEntMod(), время, требуемое, чтобы повторно вычислять и восстановить изображение полной ломаной линии, поскольку каждая вершина была изменена, будет неприемлемо медленно. Вместо этого, приложение может исполнять ряд модификаций подпримитива и затем восстанавливать изображение полного примитива с одиночным запросом к acdbEntUpd () функция.

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

    ads_name e1, e2;

    struct resbuf *ed, *cb;

    if (acdbEntNext(NULL, e1) != RTNORM) {

    acutPrintf("\nNo entities found. Empty drawing.");

    return BAD;

    }

    acdbEntNext(e1, e2);

    if ((ed = acdbEntGet(e2)) != NULL) {

    for (cb = ed; cb != NULL; cb = cb->rbnext)

    if (cb->restype == 10) { // Start point DXF code

    cb->resval.rpoint[X] = 1.0;// Change coordinates.

    cb->resval.rpoint[Y] = 2.0;

    if (acdbEntMod(ed) != RTNORM) { // Move vertex.

    acutPrintf("\nBad vertex modification.");

    acutRelRb(ed);

    return BAD;

    } else {

    acdbEntUpd(e1); // Regen the polyline.

    acutRelRb(ed);

    return GOOD; // Indicate success.

    }

    }

    acutRelRb(ed);

    }

    return BAD; // Indicate failure.

    Параметр acdbEntUpd() может определить или основной примитив или - tity; в любом случае, acdbEntUpd() восстанавливает полный примитив. Хотя его первичное использование - для сложных примитивов, acdbEntUpd() может восстанавливать любой примитив в текущем рисунке.

    ОБРАТИТЕ ВНИМАНИЕ, находится ли изменяемый примитив на блочном определении, то acdbEntUpd() функция не достаточен. Вы должны восстановить рисунок,  вызывая команду REGEN AutoCAD (с acedCmd() или acedCommand()) чтобы гарантировать, что все образцы блок-ссылок модифицированы.

    AutoCAD, Системный реестр Системы Windows, и Приложения ObjectArx

    AutoCAD использует системный реестр системы Windows, чтобы поддержать широкий диапазон прикладной информации, включая информацию, которая уникально идентифицирует различный AutoCAD, выпуск версии языка и программы (типа Карты AutoCAD ®) который может быть установлен на любом данном компьютере. Информация системного реестра, которая идентифицирует различные версии AutoCAD, имеет специфическое значение для ObjectARX разработчиков. Инсталляционная программа для приложения ObjectARX должна присоединить информацию относительно того Приложения ObjectArx с информацией относительно версии(й) AutoCAD, с которым предполагается работать.
    Программа инсталляции AutoCAD создает уникальную клавишу{*ключ*} временной метки в системном реестре немедленно ниже цифровой клавиши выпуска (также как добавление той же самой инсталляции ID к выполнимой программе непосредственно). Эта клавиша{*ключ*} гарантирует, что различные версии AutoCAD от того же самого выпуска будут способны заполнить их собственные разделы системного реестра. В пределах этой клавиши{*ключа*}, значения сохранены для местоположения файлов AutoCAD, версии языка, и названия{*имени*} изделия{*программы*}, как иллюстрировано в этом примере:
    \\HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R15.0\
    ACAD-1:409\
    ...
    AcadLocation:REG_SZ:f:\ACAD2000
    Language:REG_SZ:English
    ProductName:REG_SZ:AutoCAD Map R15.0
    ...
     Инсталляционная программа для Приложения ObjectArx должна быть способна расположить соответствующий выпуску AutoCAD клавишу{*ключ*}, также как соответствующий язык и значения программы. Клавиша{*ключ*} временной метки также используется, чтобы идентифицировать версию AutoCAD, который в настоящее время загружен (или версия, которая была наиболее недавно загружена). Эта идентификация необходима, потому что “текущая” версия AutoCAD сбрасывает информацию в глобальной переменной HKEY_CLASSES_ROOT раздел системного реестра для его собственного использования, когда это загружено.
    Значение CurVer в разделе клавиши{*ключа*} выпуска системного реестра используется, чтобы идентифицировать текущую версию, например:
     \\HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R15.0\
    ...
    CurVer:REG_SZ:ACAD-1:409
    Когда AutoCAD пытается требовать загрузку Приложение ObjectArx, это смотрит в разделе системного реестра, который принадлежит самому последнему выпуску AutoCAD для информации относительно Приложения ObjectArx. Если это не находит ObjectARX информацию там, это проверяет{*отмечает*} раздел для предыдущего выпуска AutoCAD, и так далее в обратном заказе{*порядке*}, пока информация не найдена или информация выпуска AutoCAD истощена.

    Автоматическая Отмена

    AssertWriteEnabled () функция имеет следующую сигнатуру:
    Пусто assertWriteEnabled (
    Adesk:: Булева автоотмена = Adesk:: kTrue,
    Adesk:: Булев
    recordModified = Adesk:: kTrue);
    Когда функция модификации вызывает{*называет*} assertWriteEnabled (), это сначала проверяет{*отмечает*} значение recordModified параметра. Если recordModified - kFalse, никакая регистрация отмены не выполнена. Если recordModified - kTrue, это затем проверяет{*отмечает*} параметр автоотмены, который определяет, должна ли авто операция отмены быть выполнена.
    Если автоотмена - kTrue (значение по умолчанию), полное объектное государство{*состояние*} автоматически написано к регистратору отмены объекта. Если Вы определяете kFalse для автоотмены, никакая информация не зарегистрирована. AutoCAD предполагает, что ваша функция модификации будет заботиться о регистрации измененного{*замененного*} объектного государства{*состояния*} к регистратору отмены объекта.
    Даже если Вы планируете осуществлять частичный механизм отмены для вашего класса, Вы можете полагаться на автоматическую отмену в первых стадиях развития.

     База данных Linetype Значение Масштаба

    База данных имеет три linetype параметры настройки масштаба:
    §
    установка масштаба linetype для текущего объекта, сохраненного в CELTSCALE системной переменной.
    § установка масштаба linetype для текущего рисунка, сохраненного в LTSCALE системной переменной.
    § флажок, который указывает,  применить ли linetype, масштабирующий к пространству{*пробелу*},  объект постоянно находится в или к появлению{*виду*} объекта в бумажном пространстве{*пробеле*}. Эта установка сохранена в PSLTSCALE системной переменной.
    Глобальная переменная LTSCALE и PSLTSCALE параметры настройки используется, когда рисунок восстановлен (см. главу 6, “примитивы”). Используйте следующие функции, чтобы устанавливать и запросить эти значения:
    Acad::ErrorStatus
    AcDbDatabase::setLtscale(double);
    double AcDbDatabase::ltScale() const;
    Acad::ErrorStatus
    AcDbDatabase::setCeltscale(double);
    double AcDbDatabase::celtscale() const;
    Acad::ErrorStatus
    AcDbDatabase::setPsltscale(Adesk::Boolean)
    Adesk::Boolean AcDbDatabase::psltscale() const;

     База данных Linetype Значение

    Следующий набор функций и восстанавливает{*отыскивает*} поток{*ток*} linetype значение в базе данных:
    Acad::ErrorStatus
    AcDbDatabase::setCeltype(AcDbObjectId);
    AcDbObjectId AcDbDatabase::celtype() const;

    Библиотека классов ObjectARX

    ObjectARX среда состоит из следующих групп классов и функций:
    AcRx Классы для связывания приложения и для класса во время выполнения
    регистрации и идентификации.
    AcEd Классы для регистрации команд AutoCAD и для уведомления о событиях AutoCAD.
    AcDb классы базы данных AutoCAD.
    AcGi Графические классы для исполнения объектов AutoCAD.
    AcGe Сервисные классы для общей линейной алгебры и геометрического объекта.
    Следующая таблица перечисляет библиотеки, требуемые, чтобы связать приложения ObjectARX.

    AcRx
    acad.lib, rxapi.lib, acrx15.lib
    AcEd
    acad.lib, rxapi.lib, acedapi.lib, acrx15.lib
    AcDb
    acad.lib, rxapi.lib, acdb15.lib, acrx15.lib
    AcGi
    acad.lib, rxapi.lib, acgiapi.lib, acrx15.lib
    AcGe
    acad.lib, rxapi.lib, acge15.lib, acrx15.lib

    Все приложения ObjectARX должны связаться с acad.lib и rxapi.lib. Другие библиотеки могут также требоваться в зависимости от префикса ObjectARX класса и функции, что Вы используете.
    Следующие разделы берут,  ближе смотрят на каждую из ObjectARX библиотек.
    Для получения дополнительной информации относительно определенных(удельных) классов и функций элемента, см. ObjectARX справочники.

    Блокировка документа

    Запросы Автоматизации могут быть обработаны во всех возможных контекстах AutoCAD. Это означает, что Вы ответствены за блокировку документа перед изменением этого. Будут также иметься времена, когда Вы будете хотеть делать документ “поток” временно. Например, при добавлении примитива к *MODELSPACE или *PAPERSPACE Вы должны блокировать и делать поток документа. Отказ{*неудача*} блокировать документ в некоторых контекстах вызовет нарушение “блокировки” в течение модификации базы данных. Неудача делать поток документа заставит ваш примитив быть “невидимым” в графическом дисплее (даже после регенерации).
    ObjectARX API включает функции в менеджера документа класс, чтобы делать это. Так как это - общая задача, мы формировали функциональные возможности в экспортируемый класс AcAxDocLock.
    Например:
    STDMETHODIMP CMyEntity::Modify()
    {
    AcAxDocLock docLock(m_objId, AcAxDocLock::kNormal);
    if(docLock.lockStatus() != Acad::eOk)
    {
    return E_FAIL;
    }
    // It is now safe to modify the database
    //
    return S_OK;
    }

    CAcModuleResourceOverride Класс

    Используйте образец этого класса, чтобы переключить между средствами доступа ресурса. Когда объект создан, новое средство доступа ресурса переключится в. После разрушения, первоначальное средство доступа ресурса будет восстановлено. Следующий код обеспечивает пример:
    Пусто MyFunc ()
    {
                     CAcModuleResourceOverride myResources;
    }
    После входа в эту функцию ресурсы модуля будут выбраны. Когда функциональные возвращения, заданные по умолчанию ресурсы будут восстановлены. Перегрузка ресурса может использоваться способом из трех путей:
    §
    Используют заданный по умолчанию конструктор (никакие параметры) чтобы переключить к ресурсам модуля. Заданные по умолчанию ресурсы будут восстановлены деструктором. Ресурсы модуля по умолчанию - поддерживаемые CAcExtensionModule DLL'S.
    § Передают NULL (или 0)  конструктору. Ресурсы DLL'S будут выбраны и ресурсы, которые были, в действительности будет восстановлен, когда объект перегрузки разрушен.
    § Передают дескриптор не-NULL к конструктору. Ресурсы связанного модуля будут выбраны и ресурсы, которые были, в действительности будет восстановлен, когда объект перегрузки разрушен.
    Имеются две макрокоманды если, названный AC_DECLARE_EXTENSION_MODULE и AC_IMPLEMENT_EXTENSION_MODULE, помогать определять и осуществляют классы в вашем приложении.
    Следующий код иллюстрирует, как использовать классы CAcExtensionModule и CAcModuleResourceOverride в ObjectARX-приложении:
    AC_IMPLEMENT_EXTENSION_MODULE(theArxDLL);
    HINSTANCE _hdllInstance = NULL;
    extern "C" int APIENTRY
    DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
    {
    // Remove this if you use lpReserved
    UNREFERENCED_PARAMETER(lpReserved);
    if (dwReason == DLL_PROCESS_ATTACH)
    {
    theArxDLL.AttachInstance(hInstance);
    hdllInstance = hInstance;
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    {
    theArxDLL.DetachInstance();
    }
    return 1; // ok
    }

    Черты Подпримитива

    Следующие черты (свойства) могут быть назначены на уровне подпримитивов,  вызывая функции члена объекта AcGiSubEntityTraits:
    § Color
    § Layer
    § Linetype
    § Fill type
    § GS marker
    § Line weight
    § Thickness
    § Line type scale
    Цвет, уровень, и linetype - свойства примитива AutoCAD, так что они могут также быть установлены на уровне drawable как описано в предыдущей секции. Заполните тип, и GS маркер - не свойства примитива AutoCAD.
    Перед каждым запросом к worldDraw () и viewportDraw (), AutoCAD вызывает setAttributes () чтобы позволить drawable инициализировать цвет, уровень, linetype, вес линии, толщину, и черты подпримитива масштаба типа линии. Это инициализирует, заполняют тип, чтобы соответствовать перегенеральному типу, и это инициализирует GS
    маркер, чтобы обнулить (нулевой маркер имеет значение “ никакой маркер ”).

    Чистка (Purge)

    Механизм чистки позволяет Вам стирать неиспользованные объекты в базе данных. Если объект имеет жесткого владельца или ссылку{*справочники*} указателя, это не может быть очищено. Чистка () функция AcDbDatabase вызвана на набор объектов, указанных в массиве ID:
    AcDbDatabase:: чистка (AcDbObjectIdArray &idArray);
    Purge() возвращает в том же самом ID массив ID объектов, которые могут быть очищены (то есть которые не имеют никаких жестких ссылок к ним). Как только Вы имеете этот массив объектов IDs, Вы ответствены за стирание объектов.
    Когда рисунок загружен, AutoCAD проходит базу данных и производит чистку, несослался на анонимные блоки и вложил блоки таблицы перекрестных ссылок. Эти блоки стерты, когда чертежный файл закрыт. Если Вы создаете любые анонимные блоки между открытым и близким из рисунка, они будут очищены без вашего знания, если Вы не защищаете их,  вызывая автономную функцию acdbSetReferenced (). Эта чистка происходит, даже если объекты имеют жесткие ссылки к ним.

    Цикл перетаскивания

    После того, как Вы установили подсказку дисплея для перетащенной последовательности, Вы звоните,  AcEdJig::drag() функцию, которая исполняет перетащенный цикл, пока прессы пользователя НЕ ВВОДЯТ или клавиша "пробел", или указки с устройством управления позицией. Следующий список описывает последовательность перетащенного цикла:
    1 перетащенный цикл получает случай.
    2 Это называет AcEdJig::sampler() функцией. Sampler() функция устанавливает список ключевого слова (если любой) с запросом к AcEdJig::setKeywordList() функция, специальный тип курсора (если желательно) с запросом к
    AcEdJig:: setSpecialCursorType () функция, и любой пользователь вводит средство управления с запросом к AcEdJig:: setUserInputControls () функция. Затем, это называет один из acquireXXX () функциями, чтобы получить геометрическое значение (угол, расстояние, или пункт{*точка*}). Функция всегда возвращает немедленно после опроса текущую позицию устройства управления позицией.
    3 Ваша sampler() функция должна выяснить, если имеется любое изменение{*замена*} в геометрическом дискретном значении. Если не имеется никакого изменения{*замены*}, ваш sampler () функция должна возвратить kNoChange и возвращаться, чтобы шагнуть. Это позволит изображению{*образу*} завершать его последнюю{*прошлую*} модификацию на экране. Это особенно важно для изображений{*образов*}, содержащих кривые.
    4, даже если геометрическое значение дискретный изменилось, ваш sampler() функция может возвращать kNoChange (так, чтобы изображение{*образ*} не было модифицировано) и возвращение, чтобы шагнуть.
    Если дискретное значение изменилось, и изображение{*образ*} должно быть модифицировано, перейдите шагать.
    5 dragger называет AcEdJig::update () функцией, используя приобретенное геометрическое значение, чтобы модифицировать объект.
    6 dragger тогда называет AcEdJig::entity() функцией, проходящей в указателе, который будет установлен в адрес объекта, который будет восстановлен. Затем, dragger называет worldDraw () функцией на объекте, чтобы восстановить это.
    7 Возвращения, чтобы шагнуть, если поток{*ток*} dragger случай не был сгенерирован,  выбирая с устройством управления позицией, нажимая ОТМЕНУ, или издавая строковый символ завершения, чтобы закончить перемещение.
    Следующая блок-схема показывает эти шаги.
    Цикл перетаскивания

    Цикл жизни прокси-объекта

    Прокси-объекты созданы в  AutoCAD, когда читается файл, содержащий заказные объекты, которые не могут быть действительны. Объекты пользователя не могут быть действительны, когда родительское приложение не загружено и не может пройти загрузка по требованию. Если родительское приложение впоследствии загружено в течение сессии рисунка, AutoCAD автоматически преобразовывает прокси-объекты к заказным объектам.
    О прокси(полномочным) можно думать как о обертке, содержащей заказной объект. Полномочный обеспечивает AutoCAD доступом к элементам базового класса (типа цвета и уровня) заказного объекта, и
    Это формирует членов данных заказного класса, к которым нельзя обращаться в отсутствии родительского приложения. При большинстве обстоятельств, полномочная обертка - навеска, когда база данных рисунка
    записана в файл. Тот же самый двоичный объект, который читался в,  выписан. Если сохраняющая операция вовлекает преобразование файла типа между DWG
    и DXF
    (для которого конверсионная функция родительского приложения – не загружена), полномочная обертка сохранен с заказными двоичными данными также.
    Когда родительское приложение не загружено перед записью в файл, данные обработаны следующим образом:
    §
    если файлы ввода и вывода - тот же самый файл типа (и DWG или DXF), никакая операция трансляции необходим, и те же самые данные, который читался в,  записан. Данные, сохраненные в прокси-объекте написаны к выходному файлу.
    § если файлы ввода и вывода отличаются по файлу типа (то есть DWG в DXF или наоборот), формат не может быть оттранслирован, потому что функция трансляции, определенная родительским приложением - не настоящи. Полный прокси-объект поэтому написан к выходному файлу. Когда файл впоследствии читается в соответствии с AutoCAD, полномочный или преобразует к заказному объекту (в присутствии родительского приложения), или останется полномочным в памяти (в отсутствии родительского приложения).

    CLASSID Регистрация

    Минимальная регистрация, требуемая компонентом под HKEY_CLASSES_ROOT :
    [HKEY_CLASSES_ROOT\CLSID\{ CLSID
    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx>}\
    InProcServer32]
    @="\mycomponent.arx"

    Цвет примитива

    Цвет Примитива может быть установлен и читать как числовые индексные значения в пределах от от 0 до 256, или образцами AcCmColor, который обеспечивается для будущего использования расширенной цветовой моделью. В настоящее время, цвет использований AutoCAD индексирует только. Правильный цветной индекс может быть получен от образца AcCmColor использование AcCmColor:: getColorIndex () функция члена.
    Цвет индексирует 1 до 7,  используются для стандартных цветов, как показано в следующей таблице:

    Color Number
    Color Name
    1
    Red
    2
    Yellow
    3
    Green
    4
    Cyan
    5
    Blue
    6
    Magenta
    7
    White or Black

    Цвета 8 до 255 определены устройством отображения.
    Следующие индексные значения имеют специальные значения:
    0 Определяет BYBLOCK. Примитивы наследуют цвет текущей блочной ссылки{*справочников*}, которая указывает на блочный отчет{*запись*} таблицы, что примитив постоянно находится в, или черный / белый, если примитив постоянно находится непосредственно в образцовом пространственном или бумажном пространственном блочном отчете{*записи*} таблицы.
    256 Определяет BYLAYER. Примитивы принимают цвет связанного уровня примитива.
    257 Никаких цвета. Только подарок{*настоящее*} со времени,  примитив является первым instantiated до его цвета,  установлен в значение между 0 и 256, или примитив добавлен к базе данных и принимает текущий цветной индекс базы данных.
    Если номер цвета определен для примитива, текущий номер цвета значения по умолчанию базы данных игнорируется. Используйте следующие функции, чтобы устанавливать и сделать запрос цвета примитива:
    virtual Acad::ErrorStatus
    AcDbEntity::setColorIndex(Adesk::UInt16 color);
    Adesk::UInt16
    AcDbEntity::colorIndex() const;

    Данные Класса или Xdata Номера версии

    Номер версии может быть сохранен как 8-разрядный целочисленный компонент данных (типа Adesk:: UInt8) класса, и может быть зарегистрирован в и из как первый компонент данных для каждого объекта. Поскольку эти данные постоянны, и - первое чтение элемента{*пункта*}, это может быть проверено, чтобы определить версию объекта прежде, чем любые другие данные читаются.
    Когда номер используется, чтобы дифференцировать версии объекта, родительское Приложение ObjectArx должно быть способно обработать эти два случая{*дел*} несовместимых версий объектов:
    § когда приложение сталкивается с устарелой версией объекта в файле, должно быть способно модифицировать объект к текущей версии. Модифицирование старого объекта возводит в степень добавление любых новых компонентов данных и функций элемента, также как изменения{*замены*} номера версии.
    § когда старшая версия приложения сталкивается с более новой версией объекта (то есть когда номер пересмотра объекта больший чем номер пересмотра приложения), dxfInFields заказного класса () и dwgInFields () функции должны немедленно возвратиться,  ошибка закодирует eMakeMeProxy к AutoCAD. AutoCAD тогда создаст полномочный объект для сеанса рисунка, и записывать первоначальный объект к файлу, когда рисунок сохранен.
    Возразите, что versioning с номером версии компонента данных иллюстрирован в следующих кодовых фрагментах от \objectarx\samples\polysamp\poly.cpp в ObjectARX SDK.
    // Object Version
    #define VERSION 1
    ...
    Acad::ErrorStatus
    AsdkPoly::dwgInFields(AcDbDwgFiler* filer)
    {
    ...
    // Object Version - must always be the first item
    Adesk::Int16 version;
    filer->readItem(&version);
    if (version > VERSION)
    return Acad::eMakeMeProxy;
    ...
    }
    Acad::ErrorStatus
    AsdkPoly::dwgOutFields(AcDbDwgFiler* filer) const
    {
    ...
    // Object Version - must always be the first item
    Adesk::Int16 version = VERSION;
    filer->writeItem(version);
    ...
    }
    Acad::ErrorStatus
    AsdkPoly::dxfInFields(AcDbDxfFiler* filer)
    {
    ...
    // Object Version
    case AcDb::kDxfInt16:
    Adesk::Int16 version;
    version = rb.resval.rint;
    if (version > VERSION)
    return Acad::eMakeMeProxy;
    break;
    ...
    }
    Acad::ErrorStatus
    AsdkPoly::dxfOutFields(AcDbDxfFiler* filer) const
    {
    ...
    // Object Version
    Adesk::Int16 version = VERSION;
    filer->writeItem(AcDb::kDxfInt16, version);
    ...
    }

    Данные " в документ "

    Приложения не могут сохранять данные " в документ " в глобальных или статических переменных.
    Это включает объекты AcDbDatabase, объекты AcDbObject, AcDbObjectId значения, значения переменной заголовка, значения переменной документа, наборы выбора, и другая документированная - определенная информация. Любое возникновение данных " в документ " в глобальных и статических переменных могло бы быть разрушено, если ваше приложение - работают в множественных параллельных сеансах редактирования.
    Чтобы избегать коррупции данных, Вы можете формировать поведение команды и данные в классы. Образец класса может инициализироваться для каждого запроса к команде. Поскольку команда приобретает документированные - определенные данные, это сохраняет ее собственные копии " в случай " этого данными.
    Другое решение состоит в том, чтобы формировать все глобальные и статические данные в структуру или класс. Копия данных инициализируется для каждого документа. Местный указатель на соответствующий образец установлен в каждой точке входа в приложении. Местный указатель тогда используется, чтобы обратиться к данным " в документ ".
    Используйте documentActivated () реактор, чтобы переключить между образцами скрытых данных.
    Вы можете создавать данные " в документ " на как - необходимом основании, или создавать это, когда приложение сначала загружено. Если создано на как - необходимом основании, поскольку зарегистрированные команды приложения или реакторы вызваны{*названы*}, текущий документ определен, и запрос сделан, чтобы получить данные документа. Если это не найдено, это создано в то время.
    Создавать данные " в документ " когда приложение сначала загружено, использование AcApDocumentIterator в AcRx:: kInitAppMsg обработчик, чтобы получить список всех открытых документов. Тогда используйте AcApDocManagerReactor:: documentCreated () чтобы знать, когда создать дополнительные данные " в документ " для документов, открыл после того, как приложение загружено.
    Какой бы ни метод используется, чтобы ассигновать{*разместить*} данные " в документ ", приложение должно использовать AcApDocManagerReactor::documentToBeDestroyed () реактор, чтобы знать, когда удалить данные. Приложения должны также удалить остающиеся данные в течение AcRx:: kUnloadAppMsg обработчик.

    DeepClone ()

    AcDbHardPointerId проблема ссылки, упомянутая выше не будет происходить в этом случае, потому что deepClone () не следует За AcDbHardPointerId ссылками для клонирования.
    Приложение может создавать проблемы в течение deepClone () если это пытается добавлять новые примитивы, в то время как AcDbObjectIds - все еще в состоянии непрерывного изменения. Поэтому, никогда не пытайтесь вызывать AcDbBlockTableRecord:: appendAcDbEntity () на любом клонированном, определяемом пользователем AcDbBlockTableRecords до окончания AcEditorReactor:: endDeepClone () уведомление далось. Напротив, Вы можете безопасно добавлять к пространству модели и пространству листа AcDbBlockTableRecords, потому что они никогда не клонированы в deepClone ().
    Никогда попытка добавлять вершину к клонированный AcDb2dPolylines, AcDb3dPolylines, AcDbPolyFaceMeshes, или AcDbPolygonMeshes, приписывает клонированному AcDbBlockReferences, или вхождения в клонированные словари, до окончания AcEditorReactor:: endDeepClone () уведомление.
    Если Вы создали примитивы в течение клонирования, то Вы будете должны сохранить их в памяти, наряду с ID их будущего владельца, до окончания AcEditorReactor:: endDeepClone () уведомлением. Они могут быть безопасно добавлены в конец, как только глубокий клон закончен.

    Диапазоны Кода DXF-группы

    DXF представление объекта составлено из пар кодов группы и данных, с каждым отображением кода группы к определенному типу данных. Когда Вы определяете ваше собственное DXF представление, первая группа данных Вы записываете и читаете, должен быть маркер данных подкласса. Этот маркер состоит из  кода группы 100, сопровождаемых строкой, которая является текущим именем класса. Тогда, Вы выбираете коды группы от следующей таблицы, которые соответствуют типам данных каждого поля данных, которое Вы записываете.
    DXF group code ranges for object representation

    From
    To
    Data Type
    1
    4
    Text
    6
    9
    Text
    10
    17
    Point or vector (3 reals)
    38
    59
    Real
    60
    79
    16-bit integer
    90
    99
    32-bit integer
    100
    100
    Subclass data marker
    102
    102
    Text
    140
    149
    Real
    170
    179
    16-bit integer
    210
    219
    3 reals
    270
    279
    16-bit integer
    280
    289
    8-bit integer
    300
    309
    Text
    310
    319
    Binary chunk
    320
    329
    Handle
    330
    339
    Soft Pointer ID
    340
    349
    Hard Pointer ID
    350
    359
    Soft owner ID
    360
    369
    Hard owner ID

    Объект ID транслирует к rlname. Например, AcDbObjectId соответствует ads_name, который представлен в resval объединении как rlname.
    Порядок зависимости
    С DXF, по усмотрению автора класса, группы данных могут быть представлены в произвольном порядке, или произвольно опущен. Некоторые классы поддерживают независимость порядка групп данных, в то время как другие делают нет. Если Вы позволяете независимость порядка, то ваш dxfInFields () функция должен использовать инструкцию выключателя, чтобы выбрать действие, основанное на значении кода группы. Независимость порядка обычно соответствующая объектам с фиксированным и предсказуемым набором полей. Объекты с массивами переменной длины или структурами имеют тенденцию быть иждивенцем заказа, когда они зарегистрированы из и в.
    Типовой Код для dxfOutFields ()

    Следующее - типовой код от AsdkPoly:: dxfOutFields ():

    Acad::ErrorStatus

    AsdkPoly::dxfOutFields(AcDbDxfFiler* filer) const

    {

    assertReadEnabled();

    Acad::ErrorStatus es;

    if ((es = AcDbCurve::dxfOutFields(filer))

    != Acad::eOk)

    {

    return es;

    }

    filer->writeItem(AcDb::kDxfSubclass, "AsdkPoly");

    // Object Version

    //

    Adesk::Int16 version = VERSION;

    filer->writeInt16(AcDb::kDxfInt16, version);

    filer->writePoint2d(AcDb::kDxfXCoord, mCenter);

    filer->writePoint2d(AcDb::kDxfXCoord + 1, mStartPoint);

    filer->writeInt32(AcDb::kDxfInt32, mNumSides);

    // Always use max precision when writing out the normal.

    filer->writeVector3d(AcDb::kDxfNormalX, mPlaneNormal,16);

    filer->writeString(AcDb::kDxfText, mpName);

    filer->writeItem(AcDb::kDxfHardPointerId, mTextStyle);

    filer->writeDouble(AcDb::kDxfReal, mElevation);

    return filer->filerStatus();

    }

    Типовой Код для dxfInFields () с Независимостью порядка

    Следующее - типовой код для AsdkPoly:: dxfInFields ():

    Acad::ErrorStatus

    AsdkPoly::dxfInFields(AcDbDxfFiler* filer)

    {

    assertWriteEnabled();

    Acad::ErrorStatus es = Acad::eOk;

    resbuf rb;

    if ((AcDbCurve::dxfInFields(filer) != Acad::eOk) || !filer->atSubclassData("AsdkPoly"))

    {

    return filer->filerStatus();

    }

    // Object Version

    Adesk::Int16 version;

    filer->readItem(&rb);

    if (rb.restype != AcDb::kDxfInt16)

    {

    filer->pushBackItem();

    filer->setError(Acad::eInvalidDxfCode,

    "\nError: expected group code %d (version)",

    AcDb::kDxfInt16);

    return filer->filerStatus();

    }

    version = rb.resval.rint;

    if (version > VERSION)

    return Acad::eMakeMeProxy;

    AcGePoint3d cen3d,sp3d;

    AcGePoint2d cen2d,sp2d;

    long numSides;

    AcDbObjectId textStyle;

    double elevation;

    Adesk::UInt32 fieldsFlags = 0;

    char * pName = NULL;

    AcGeVector3d planeNormal;

    while ((es == Acad::eOk) && ((es = filer->readResBuf(&rb)) == Acad::eOk))

    {

    switch (rb.restype) {


    case AcDb::kDxfXCoord:

    if (version == 1)

    cen3d = asPnt3d(rb.resval.rpoint);

    else

    cen2d = asPnt2d(rb.resval.rpoint);

    fieldsFlags |= 0x1;

    break;

    case AcDb::kDxfXCoord + 1:

    if (version == 1)

    sp3d = asPnt3d(rb.resval.rpoint);

    else

    sp2d = asPnt2d(rb.resval.rpoint);

    fieldsFlags |= 0x2;

    break;

    case AcDb::kDxfInt32:

    numSides = rb.resval.rlong;

    fieldsFlags |= 0x4;

    break;

    case AcDb::kDxfNormalX:

    planeNormal = asVec3d(rb.resval.rpoint);

    fieldsFlags |= 0x8;

    break;

    case AcDb::kDxfText:

    acutUpdString(rb.resval.rstring,pName);

    fieldsFlags |= 0x11;

    break;

    case AcDb::kDxfHardPointerId:

    acdbGetObjectId(textStyle, rb.resval.rlname);

    fieldsFlags |= 0x12;

    break;

    case AcDb::kDxfReal:

    if (version == 2)

    {

    fieldsFlags |= 0x10;

    elevation = rb.resval.rreal;

    break;

    }

    //fall through intentional

    default:

    // An unrecognized group. Push it back so that

    // the subclass can read it again.

    filer->pushBackItem();

    es = Acad::eEndOfFile;

    break;

    }

    }

    // At this point, the es variable must contain eEndOfFile,

    // either from readResBuf() or from pushbackBackItem(). If

    // not, it indicates that an error happened and we should

    // return immediately.

    //

    if (es != Acad::eEndOfFile)

    return Acad::eInvalidResBuf;

    // Now check to be sure all necessary group codes were

    // present.

    //

    // Mandatory fields:

    // - center

    // - start point

    // - normal

    // - number of sides

    // - elevation (if version > 1)

    short required[] =

    {AcDb::kDxfXCoord, AcDb::kDxfXCoord+1, AcDb::kDxfInt32,

    AcDb::kDxfNormalX, AcDb::kDxfReal};

    for (short i = 0; i < (version>1?4:3); i++) {

    if (!fieldsFlags & 0x1) {

    filer->setError(Acad::eMissingDxfField,

    "\nMissing DXF group code: %d", 2, required[i]);

    return Acad::eMissingDxfField;

    } else

    fieldsFlags >>= 1;

    }

    mPlaneNormal = planeNormal;

    mNumSides = numSides;

    mTextStyle = textStyle;

    setName(pName);

    acutDelString(pName);

    if (version==1)

    {

    //convert data from old format

    acdbWcs2Ecs(asDblArray(cen3d),asDblArray(cen3d),


    asDblArray(planeNormal),Adesk::kFalse);

    mCenter.set(cen3d.x,cen3d.y);

    mElevation = cen3d.z;

    acdbWcs2Ecs(asDblArray(sp3d),asDblArray(sp3d),

    asDblArray(planeNormal),Adesk::kFalse);

    mStartPoint.set(sp3d.x,sp3d.y);

    assert(mElevation == sp3d.z);

    } else {

    mCenter = cen2d;

    mStartPoint = sp2d;

    mElevation = elevation;

    }

    return es;

    }

    Законченный код для AsdkPoly определенного приложением класса может быть найден в каталоге примеров.

    Типовой Код для dxfInFields () с  порядком зависимостей

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

    Acad::ErrorStatus

    AsdkPoly::dxfInFields(AcDbDxfFiler* filer)

    {

    assertWriteEnabled();

    if ((AcDbCurve::dxfInFields(filer) != Acad::eOk) || !filer->atSubclassData("AsdkPoly") )

    {

    return filer->filerStatus();

    }

    try

    {

    struct resbuf rb;

    // Object Version

    Adesk::Int16 version;

    filer->readItem(&rb);

    if (rb.restype != AcDb::kDxfInt16)

    throw AcDb::kDxfInt16;

    version = rb.resval.rint;

    if (version > VERSION)

    return Acad::eMakeMeProxy;

    if (version == 1)

    {

    AcGePoint3d cent,sp;

    filer->readItem(&rb);

    if (rb.restype != AcDb::kDxfXCoord)

    throw AcDb::kDxfXCoord

    cent = asPnt3d(rb.resval.rpoint);

    filer->readItem(&rb);

    if (rb.restype != AcDb::kDxfXCoord + 1)

    throw AcDb::kDxfXCoord + 1;

    sp = asPnt3d(rb.resval.rpoint);

    filer->readItem(&rb);

    if (rb.restype != AcDb::kDxfInt32)

    throw AcDb::kDxfInt32;

    mNumSides = rb.resval.rlong;

    filer->readItem(&rb);

    if (rb.restype != AcDb::kDxfNormalX)

    throw AcDb::kDxfNormalX

    mPlaneNormal = asVec3d(rb.resval.rpoint);

    filer->readItem(&rb);

    if (rb.restype != AcDb::kDxfText)

    throw AcDb::kDxfText;

    setName(rb.resval.rstring);

    filer->readItem(&rb);

    if (rb.restype != kDxfHardPointerId)

    throw AcDb::kDxfHardPointerId;

    acdbGetObjectId(mTextStyle, rb.resval.rlname);


    // Convert data from old format.

    acdbWcs2Ecs(asDblArray(cent),asDblArray(cent),

    asDblArray(mPlaneNormal),Adesk::kFalse);

    mCenter.set(cent.x,cent.y);

    mElevation = cent.z;

    acdbWcs2Ecs(asDblArray(sp),asDblArray(sp),

    asDblArray(mPlaneNormal),Adesk::kFalse);

    mStartPoint.set(sp.x,sp.y);

    assert(mElevation == sp.z);

    }

    else if (version == 2)

    {

    filer->readItem(&rb);

    if (rb.restype != AcDb::kDxfXCoord)

    throw AcDb::kDxfXCoord;

    mCenter = asPnt2d(rb.resval.rpoint);

    filer->readItem(&rb);

    if (rb.restype != AcDb::kDxfXCoord + 1)

    throw AcDb::kDxfXCoord + 1;

    mStartPoint = asPnt2d(rb.resval.rpoint);

    filer->readItem(&rb);

    if (rb.restype != AcDb::kDxfInt32)

    throw AcDb::kDxfInt32

    mNumSides = rb.resval.rlong;

    filer->readItem(&rb);

    if (rb.restype != AcDb::kDxfNormalX)

    throw AcDb::kDxfNormalX;

    mPlaneNormal = asVec3d(rb.resval.rpoint);

    filer->readItem(&rb);

    if (rb.restype != AcDb::kDxfText)

    throw AcDb::kDxfText

    setName(rb.resval.rstring);

    filer->readItem(&rb);

    if (rb.restype != AcDb::kDxfHardPointerId)

    throw AcDb::kDxfHardPointerId;

    acdbGetObjectId(mTextStyle, rb.resval.rlname);

    filer->readItem(&rb);

    if (rb.restype != AcDb::kDxfReal)

    throw AcDb::kDxfReal;

    mElevation = rb.resval.rreal;

    }

    else assert(false);

    }

    catch (AcDb::DxfCode code)

    {

    filer->pushBackItem();

    filer->setError(Acad::eInvalidDxfCode,

    "\nError: expected group code %d", code);

    return filer->filerStatus();

    }

    }





    Длинные транзакции

    Длинные транзакции используются, чтобы поддержать Особенность редактирования Ссылки{*справочников*} AutoCAD и очень полезны для Приложений ObjectArx. Эти классы и функции обеспечивают схему приложений, чтобы проверить объекты для редактирования и проверяют{*отмечают*} их назад в к их первоначальному местоположению. Эта операция заменяет первоначальные объекты отредактированными. Имеются три типа длинного операционного контроля:
    § От нормального блока в пределах того же самого рисунка
    § От внешней ссылки (таблица перекрестных ссылок) рисунка
    § От несвязанной, временной базы данных

    Для Всех Операционных систем

    Модифицируйте путь к приложению для каждой операционной системе. Используя сценарий InstallShield, это может быть сделано следующим способом. (SzAppPath принят, чтобы включить общедоступный путь и любые другие пути, требуемые вашим приложением.)
    szExe = "your.exe";
    szProdKey = "Software\\Microsoft\\Windows\\";
    szProdKey = szProdKey + "CurrentVersion\\App Paths\\" + szExe;
    RegDBSetKeyValueEx(szProdKey, "Path", REGDB_STRING, szAppPath, -1);

    Добавление Функциональных возможностей к Объектной Модели

    В самом простом случае, ваш класс обертки COM выставит{*подвергнет*} один или большее количество функций, которые Вы хотели бы делать доступным разработчикам, использующим среды программирования типа VBA.
    Создавать обертку Автоматизации для ObjectARX-приложения
    1 Основанный ваш проект согласно шагам в “ Введение Файла Проекта ATL. ”
    2 В файле заголовка объекта COM, добавьте #include "Axtempl.h" (главное ActiveX файл заголовка шаблона Автоматизации).
    3, если Вы хотите,  прикладное свойство, добавляет следующий вход в COM_MAP:
     COM_INTERFACE_ENTRY(IRetrieveApplication)
    4 В файле IDL, добавьте importlib ("c:\ACAD\acad.tlb"); после importlib stdole32.tlb и importlib stdole2.tlb. Удостоверитесь, чтобы использовать правильный путь, который соответствует вашей инсталляции AutoCAD.
    5, если ObjectARX-приложение и обертка COM объединено, добавьте следующий код к вашему главному CPP файл, и назовите это DllMain в AcRx:: kInitAppMsg и AcRx:: kUnloadAppMsg с соответствующими параметрами.
    Это инициализирует карту объекта ATL, среди других вещей.
    extern "C" HINSTANCE _hdllInstance;
    extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance,
    DWORD dwReason,LPVOID /*lpReserved*/);
    6 Компоновки и регистр приложение согласно шагам в “ Формирование и Регистрация COM DLL. ”

    Добавление Группы к Словарю Группы

    Cледующий код создает группу (pGroup) из линии и круга, созданного в createLine () и createCircle (),  и помещает группу в словарь GROUP. Объект IDs линии и круга пропускают в функцию. Обратите внимание, как словарь GROUP открыт для записи, изменяется, и затем явно закрыт.
    void
    createGroup(AcDbObjectIdArray& objIds, char* pGroupName)
    {
    AcDbGroup *pGroup = new AcDbGroup(pGroupName);
    for (int i = 0; i < objIds.length(); i++) {
    pGroup->append(objIds[i]);
    }
    // Put the group in the group dictionary that resides
    // in the named object dictionary.
    //
    AcDbDictionary *pGroupDict;
    acdbHostApplicationServices()->workingDatabase()
    ->getGroupDictionary(pGroupDict, AcDb::kForWrite);
    AcDbObjectId pGroupId;
    pGroupDict->setAt(pGroupName, pGroup, pGroupId);
    pGroupDict->close();
    pGroup->close();
    }

    Добавление Объектно - определенных Данных

    Вы можете использовать любой из четырех механизмов для добавления образец-определенных данных в вашем приложении:
  • Расширенные{*продленные*} данные (xdata)

  • Xrecords (см. главу 7, “ Контейнерные Объекты ”)

  • словари Расширений{*продления*} любого объекта

  • Объекты пользователя, которые могут держаться, данные (видят главу 12, “ Происходящий от AcDbObject ”)


  • Добавлять свойства

    1 Идут к Представлению Класса в IDE Visual C++, щелкают правой кнопкой мыши на заказном интерфейсе примитива (типа IAsdkSquareWrapper), и выбирают AddProperty.
    2 Для Типа Свойства, выберите Двойной. Для Имени Свойства, выберите свойство (типа SquareSize). Оставьте пробел параметров.
    3 В заглушке, что Мастер, созданный для Вас, добавьте следующий код запроса (типа функции get_SquareSize от выборки многоугольника):
    AcDbObjectPointer pSq(m_objId, AcDb::kForRead);
    if (pSq.openStatus() != Acad::eOk)
    return E_ACCESSDENIED;
    double size;
    pSq->squareSideLength(size);
    *pVal = size;
    return S_OK;
    4 В заглушке, которую Мастер создавал, добавьте следующий код модификации (типа функции put_SquareSize от выборки многоугольника):
    AcDbObjectPointer pSq(m_objId, AcDb::kForWrite);
    if (pSq.openStatus() != Acad::eOk)
    return E_ACCESSDENIED;
    pSq->setSquareSideLength(newVal);
    return S_OK;
    5 В AutoCAD, загрузите приложение (типа squareui.arx) и выполните команду, чтобы создать заказной примитив.
    6 Удостоверятся, ЧТО OPM загружен. Выберите объект. Вы должны видеть и быть способными изменить общие свойства примитив и побочная длина. Обратите внимание, что SquareSize свойство отображает под “Общей” категорией.

    Добавьте Код, чтобы Поддержать Новый Объект COM ATL

    1 Теперь мы должны добавить код, чтобы поддержать новый интерфейс. Сначала добавьте включающийся для dcapi.idl файла AsdkDesignCenterSamp .idl. Это включает, должен быть сделан после двух заданного по умолчанию импорта:
    import "oaidl.idl";
    import "ocidl.idl";
    #include "dcapi.idl"
    2 Открывают AsdkDcContent .h файл заголовка и изменяют{*заменяют*} образование для нового класса, чтобы включить CWINDOWIMPLBASE и IAcDcContentView следующим образом:
    class ATL_NO_VTABLE CAsdkDcContent :
    public CComObjectRootEx,
    public CComCoClass,
    public ISupportErrorInfo,
    public IDispatchImpl &LIBID_ASDKDESIGNCENTERSAMPLib>,
    public CWindowImplBase,
    public IAcDcContentView
    {
    3 Теперь вводят интерфейсы объекта в карту COM, используя макрокоманду COM_INTERFACE_ENTRY:
    BEGIN_COM_MAP(CAsdkDcContent)
    COM_INTERFACE_ENTRY(IAsdkDcContent)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(ISupportErrorInfo)
    COM_INTERFACE_ENTRY(IAcDcContentView)
    END_COM_MAP()
    4 Добавляют карту сообщения к классу:
    BEGIN_MSG_MAP(CAsdkDcContent)
    END_MSG_MAP()
    5 Добавляют следующие объявления для интерфейса IAcDcContentView и некоторых сервисных методов:
    public:
    void OpenAndDisplayTextFile();
    void OpenAndInsertTextFile();
    CString OpenAndReadTextFile(DWORD& length);
    STDMETHOD(Initialize)(/*[in]*/ VARIANT varBrowser);
    STDMETHOD(SetImageLists)();
    STDMETHOD(NavigatorNodeExpanding)(
    /*[in]*/ VARIANT varhNode
    , /*[in]*/ BSTR bstrFullPath);
    STDMETHOD(NavigatorNodeCollapsing)(
    /*[in]*/ VARIANT varhNode
    , /*[in]*/ BSTR bstrFullPath);
    STDMETHOD(NavigatorNodeClick)(
    /*[in]*/ VARIANT varhNode
    , /*[in, string]*/ BSTR bstrFullPath);
    STDMETHOD(NavigatorMouseUp)(
    /*[in]*/ VARIANT varhNode
    , /*[in, string]*/ BSTR bstrFullPath
    , /*[in]*/ VARIANT varX
    , /*[in]*/ VARIANT varY);
    STDMETHOD(PaletteItemClick)(/*[in]*/ BSTR bstrItemText);

    STDMETHOD(PaletteItemDblClick)(/*[in]*/ BSTR bstrItemText);

    STDMETHOD(PaletteColumnClick)(/*[in]*/ VARIANT varIndex);

    STDMETHOD(PaletteMouseUp)(

    /*[in]*/ VARIANT varButton

    , /*[in]*/ VARIANT varItemTexts

    , /*[in]*/ VARIANT varX

    , /*[in]*/ VARIANT varY);

    STDMETHOD(PaletteMouseDown)(

    /*[in]*/ VARIANT varButton

    , /*[in]*/ BSTR bstrFullText

    , /*[in]*/ VARIANT varX

    , /*[in]*/ VARIANT varY);

    STDMETHOD(RenderPreviewWindow)(

    /*[in]*/ BSTR bstrFullText

    , /*[in]*/ VARIANT varhPreviewWindow);

    STDMETHOD(PreviewMouseUp)(

    /*[in]*/ VARIANT varButton

    , /*[in]*/ VARIANT varX

    , /*[in]*/ VARIANT varY);

    STDMETHOD(Refresh)();

    STDMETHOD(PaletteBeginDrag)(

    /*[in]*/ VARIANT varItemTexts

    , /*[in]*/ VARIANT varX

    , /*[in]*/VARIANT varY);

    STDMETHOD(ReleaseBrowser)();

    STDMETHOD(QueryContextMenu)(

    /*[in]*/ VARIANT varhMenu

    , /*[in]*/ VARIANT varIndex

    , /*[in]*/ VARIANT varCmdFirst

    , /*[in]*/ VARIANT varCmdLast

    , /*[in]*/ VARIANT varItemTexts);

    STDMETHOD(InvokeCommand)(/*[in]*/ VARIANT varMenuID);

    STDMETHOD(IsExpandable)(

    /* [string][in] */ BSTR bstrItemText

    , /* [retval][out] */ VARIANT __RPC_FAR

    *pvarIsExpandable);

    STDMETHOD(GetLargeImage)(

    /* [in] */ BSTR bstrFileName

    , /* [out][in] */ VARIANT __RPC_FAR

    *pvarhLargeImage);

    STDMETHOD(GetSmallImageListForContent)(

    /*[in]*/ BSTR bstrFileName

    , /*[out]*/ VARIANT *pvarhImageList);

    STDMETHOD(GetLargeImageListForContent)(

    /*[in]*/ BSTR bstrFileName

    , /*[out]*/ VARIANT *pvarhImageList);

    private:

    char * m_strSelectedItemText;

    IAcDcContentBrowser* m_pBrowser;

    6 Добавляют код, чтобы осуществить методы, только добавленные. Обратите внимание, что многие из этих методов только необходимы закончить интерфейс. Пример использует одиночный щелчок (PaletteItemClick) и двойной щелчок (PaletteItemDblClick) события.

    Adesk::Boolean append(AcDbEntity* pEntity)

    {

    AcDbBlockTable *pBlockTable;

    AcApDocument* pDoc = acDocManager->curDocument();

    Acad::ErrorStatus es = acDocManager->lockDocument(pDoc);

    if (es != Acad::eOk) {


    acedAlert("Failed to lock the document!");

    return Adesk::kFalse;

    }

    AcDbDatabase* pDb = pDoc->database();

    es = pDb->getBlockTable(pBlockTable, AcDb::kForRead);

    if (es != Acad::eOk) {

    acedAlert("Failed to get block table!");

    return Adesk::kFalse;

    }

    AcDbBlockTableRecord *pBlockRec;

    es = pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockRec,

    AcDb::kForWrite);

    if (es != Acad::eOk) {

    acedAlert(" Failed to get block table record!");

    pBlockTable->close();

    return Adesk::kFalse;

    }

    es = pBlockRec->appendAcDbEntity(pEntity);

    if (es != Acad::eOk) {

    acedAlert("Failed to append entity!");

    pBlockTable->close();

    pBlockRec->close();

    delete pEntity;

    return Adesk::kFalse;

    }

    pBlockRec->close();

    pBlockTable->close();

    acDocManager->unlockDocument(pDoc);

    return Adesk::kTrue;

    }

    STDMETHODIMP CAsdkDcContent::Initialize(VARIANT varBrowser)

    {

    m_pBrowser = (IAcDcContentBrowser*)varBrowser.punkVal;

    m_pBrowser->AddRef();

    return S_OK;

    }

    STDMETHODIMP CAsdkDcContent::SetImageLists()

    {

    return S_OK;

    }

    STDMETHODIMP CAsdkDcContent::NavigatorNodeExpanding(

    VARIANT varhNode,

    BSTR bstrFullPath)

    {

    return S_OK;

    }

    STDMETHODIMP CAsdkDcContent::NavigatorNodeCollapsing(

    VARIANT varhNode,

    BSTR bstrFullPath)

    {

    return S_OK;

    }

    STDMETHODIMP CAsdkDcContent::NavigatorNodeClick(

    VARIANT varhNode,

    BSTR bstrFullPath)

    {

    return S_OK;

    }

    STDMETHODIMP CAsdkDcContent::NavigatorMouseUp(

    VARIANT varhNode,

    BSTR bstrFullPath,

    VARIANT varX,

    VARIANT varY)

    {

    return S_OK;

    }

    CString CAsdkDcContent::OpenAndReadTextFile(DWORD& length)

    {

    CFile fileText;

    fileText.Open(m_strSelectedItemText, CFile::modeRead);

    length = fileText.GetLength();

    char *strBuff = new char[length];

    fileText.Read(strBuff, length);

    fileText.Close();

    CString cstrBuff(strBuff);

    delete strBuff;

    cstrBuff.SetAt(length, ’\0’);

    cstrBuff.FreeExtra();

    return cstrBuff;

    }


    void CAsdkDcContent::OpenAndDisplayTextFile()

    {

    DWORD length;

    CString cstrBuff = OpenAndReadTextFile(length);

    BSTR bstrBuf = cstrBuff.AllocSysString();

    m_pBrowser->SetItemDescription(bstrBuf);

    ::SysFreeString(bstrBuf);

    }

    STDMETHODIMP CAsdkDcContent::PaletteItemClick(BSTR bstrItemText)

    {

    USES_CONVERSION;

    m_strSelectedItemText = OLE2T(bstrItemText);

    OpenAndDisplayTextFile();

    return S_OK;

    }

    void CAsdkDcContent::OpenAndInsertTextFile()

    {

    DWORD length;

    CString cstrBuff = OpenAndReadTextFile(length);

    cstrBuff.Replace("\015\012", "\\P");

    struct resbuf resbufViewCtr;

    resbufViewCtr.restype = RT3DPOINT;

    acedGetVar("VIEWCTR", &resbufViewCtr);

    AcGePoint3d pt(resbufViewCtr.resval.rpoint[X],

    resbufViewCtr.resval.rpoint[Y],

    resbufViewCtr.resval.rpoint[Z]);

    AcDbMText *pMText = new AcDbMText();

    pMText->setLocation(pt);

    pMText->setContents(cstrBuff);

    append(pMText);

    pMText->downgradeOpen();

    pMText->draw();

    pMText->close();

    }

    STDMETHODIMP CAsdkDcContent::PaletteItemDblClick(

    BSTR bstrItemText)

    {

    USES_CONVERSION;

    m_strSelectedItemText = OLE2T(bstrItemText);

    OpenAndInsertTextFile();

    return S_OK;

    }

    STDMETHODIMP CAsdkDcContent::PaletteColumnClick(

    VARIANT varIndex)

    {

    return S_OK;

    }

    STDMETHODIMP CAsdkDcContent::PaletteMouseUp(

    VARIANT varButton,

    VARIANT varItemTexts,

    VARIANT varX,

    VARIANT varY)

    {

    return S_OK;

    }

    STDMETHODIMP CAsdkDcContent::PaletteMouseDown(

    VARIANT varButton,

    BSTR bstrFullText,

    VARIANT varX, VARIANT varY)

    {

    return S_OK;

    }

    STDMETHODIMP CAsdkDcContent::RenderPreviewWindow(

    BSTR bstrFullText,

    VARIANT varhPreviewWindow)

    {

    return S_OK;

    }

    STDMETHODIMP CAsdkDcContent::PreviewMouseUp(

    VARIANT varButton,

    VARIANT varX,

    VARIANT varY)

    {

    return S_OK;

    }

    STDMETHODIMP CAsdkDcContent::Refresh()

    {

    return S_OK;

    }

    STDMETHODIMP CAsdkDcContent::PaletteBeginDrag(

    VARIANT varItemTexts,

    VARIANT varX,


    VARIANT varY)

    {

    return S_OK;

    }

    STDMETHODIMP CAsdkDcContent::ReleaseBrowser()

    {

    return S_OK;

    }

    STDMETHODIMP CAsdkDcContent::QueryContextMenu(

    VARIANT varhMenu,

    VARIANT varIndex,

    VARIANT varCmdFirst,

    VARIANT varCmdLast,

    VARIANT varItemTexts)

    {

    return S_OK;

    }

    STDMETHODIMP CAsdkDcContent::InvokeCommand(VARIANT varMenuID)

    {

    return S_OK;

    }

    STDMETHODIMP

    CAsdkDcContent::IsExpandable(

    /* [string][in] */ BSTR bstrItemText,

    /* [retval][out] */ VARIANT __RPC_FAR *pvarIsExpandable)

    {

    pvarIsExpandable->iVal = TRUE;

    return S_OK;

    }

    STDMETHODIMP

    CAsdkDcContent::GetLargeImage(

    /* [in] */ BSTR bstrFileName,

    /* [out][in] */ VARIANT __RPC_FAR *pvarhLargeImage)

    {

    return E_NOTIMPL;

    }

    STDMETHODIMP

    CAsdkDcContent::GetSmallImageListForContent(

    BSTR bstrFileName,

    VARIANT *pvarhImageList)

    {

    return E_NOTIMPL;

    }

    STDMETHODIMP

    CAsdkDcContent::GetLargeImageListForContent(

    BSTR bstrFileName,

    VARIANT *pvarhImageList)

    {

    return E_NOTIMPL;

    }

    7 Теперь включают соответствующие файлы заголовка в sdtafx.h файл. Вы будете также должны добавить определение, чтобы неопределить _DEBUG, так как библиотеки AutoCAD - не-отладка. Имеется то, что файл должен напомнить:

    #if defined(_DEBUG) && !defined(ARX_DEBUG)

    #undef _DEBUG

    #define ARX_DEBUG

    #endif



    #if _MSC_VER > 1000

    #pragma once

    #endif // _MSC_VER > 1000

    #define STRICT

    #ifndef _WIN32_WINNT

    #define _WIN32_WINNT 0x0400

    #endif

    #define _ATL_APARTMENT_THREADED

    #include

    #include

    #include

    // You may derive a class from CComModule and use

    // it if you want to override something, but do not

    // change the name of _Module.

    //

    extern CComModule _Module;

    #include



    #include

    #include

    #include

    #include

    #include

    #include

    #include

    #include



    #ifdef ARX_DEBUG

    #undef ARX_DEBUG

    #define _DEBUG

    #endif

    Добавьте Код к Обработчикам

    Как только Вы добавили обработчики, Вы готовы добавить код, чтобы иметь дело с вашим диалогом. Этот раздел суммирует то, что каждый обработчик делает с законченной распечаткой.
    1 Сначала мы добавляем несколько сервисных функций, чтобы конвертировать{*преобразовывать*}, отображать, и проверить правильность значений.
    Примечание мы использует CACUINUMERIC и средство управления CACUIANGLEEDIT, чтобы делать это:
    // Utility functions
    void AsdkAcUiDialogSample::DisplayPoint()
    {
    m_ctrlXPtEdit.SetWindowText(m_strXPt);
    m_ctrlXPtEdit.Convert();
    m_ctrlYPtEdit.SetWindowText(m_strYPt);
    m_ctrlYPtEdit.Convert();
    m_ctrlZPtEdit.SetWindowText(m_strZPt);
    m_ctrlZPtEdit.Convert();
    }
    bool AsdkAcUiDialogSample::ValidatePoint()
    {
    if (!m_ctrlXPtEdit.Validate())
    return false;
    if (!m_ctrlYPtEdit.Validate())
    return false;
    if (!m_ctrlZPtEdit.Validate())
    return false;
    return true;
    }
    void AsdkAcUiDialogSample::DisplayAngle()
    {
    m_ctrlAngleEdit.SetWindowText(m_strAngle);
    m_ctrlAngleEdit.Convert();
    }
    bool AsdkAcUiDialogSample::ValidateAngle()
    {
    if (!m_ctrlAngleEdit.Validate())
    return false;
    return true;
    }
    2 Теперь добавляют некоторые сервисные функции, чтобы выполнить итерации более чем двух таблиц идентификаторов и отображать названия{*имена*} в двух различных списках:
    void AsdkAcUiDialogSample::DisplayBlocks()
    {
    AcDbBlockTable *pBlockTable;
    acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pBlockTable, AcDb::kForRead);
    // Iterate through the block table and display
    // the names in the list box.
    //
    char *pName;
    AcDbBlockTableIterator *pBTItr;
    if (pBlockTable->newIterator(pBTItr) == Acad::eOk) {
    while (!pBTItr->done()) {
    AcDbBlockTableRecord *pRecord;
    if (pBTItr->getRecord(pRecord, AcDb::kForRead)
    == Acad::eOk) {
    pRecord->getName(pName);
    m_ctrlBlockListBox.InsertString(-1, pName);
    pRecord->close();
    }
    pBTItr->step();
    }
    }
    pBlockTable->close();
    }
    void AsdkAcUiDialogSample::DisplayRegApps()

    {

    AcDbRegAppTable *pRegAppTable;

    acdbHostApplicationServices()->workingDatabase()

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

    // Iterate through the reg app table and display the

    // names in the list box.

    //

    char *pName;

    AcDbRegAppTableIterator *pItr;

    if (pRegAppTable->newIterator(pItr) == Acad::eOk) {

    while (!pItr->done()) {

    AcDbRegAppTableRecord *pRecord;

    if (pItr->getRecord(pRecord, AcDb::kForRead)

    == Acad::eOk) {

    pRecord->getName(pName);

    m_ctrlRegAppComboBox.InsertString(-1, pName);

    pRecord->close();

    }

    pItr->step();

    }

    }

    pRegAppTable->close();

    }

    3 Добавляют объявления для функций и переменных к определению класса файл заголовка:

    void DisplayPoint();

    bool ValidatePoint();

    void DisplayAngle();

    bool ValidateAngle();

    void DisplayBlocks();

    void DisplayRegApps();

    CString m_strAngle;

    CString m_strXPt;

    CString m_strYPt;

    CString m_strZPt;

    4 Затем - обработчики кнопки для выбора точки и угла, используя редактора AutoCAD. Обратите внимание, как BeginEditorCommand (), CompleteEditorCommand (), и CancelEditorCommand () функции используются, чтобы скрыть диалог, позволять запрос к acedGetPoint и acedGetAngle, и наконец или отменять или восстанавливать изображение диалога, основанного на как выбранный пользователь:

    // AsdkAcUiDialogSample обработчики сообщения

    void AsdkAcUiDialogSample::OnButtonPoint()

    {

    // Hide the dialog and give control to the editor

    //

    BeginEditorCommand();

    ads_point pt;

    // Get a point

    //

    if (acedGetPoint(NULL, "\nPick a point: ", pt) == RTNORM) {

    // If the point is good, continue

    //

    CompleteEditorCommand();

    m_strXPt.Format("%g", pt[X]);

    m_strYPt.Format("%g", pt[Y]);

    m_strZPt.Format("%g", pt[Z]);

    DisplayPoint();

    } else {

    // otherwise cancel the command (including the dialog)

    CancelEditorCommand();

    }

    }

    void AsdkAcUiDialogSample::OnButtonAngle()

    {

    // Hide the dialog and give control to the editor


    //

    BeginEditorCommand();

    // Set up the default point for picking an angle

    // based on the m_strXPt, m_strYPt, and m_strZPt values

    //

    ads_point pt;

    acdbDisToF(m_strXPt, -1, &pt[X]);

    acdbDisToF(m_strYPt, -1, &pt[Y]);

    acdbDisToF(m_strZPt, -1, &pt[Z]);

    double angle;

    // Get a point from the user

    //

    if (acedGetAngle(pt, "\nPick an angle: ", &angle) == RTNORM) {

    // If we got an angle, go back to the dialog

    //

    CompleteEditorCommand();

    // Convert the acquired radian value to degrees since the

    // AcUi control can convert that to the other formats.

    //

    m_strAngle.Format("%g", angle*(180.0/PI));

    DisplayAngle();

    } else {

    // otherwise cancel the command (including the dialog)

    //

    CancelEditorCommand();

    }

    }

    5 Теперь обработчики окна редактирования осуществлены. В основном мы только хотим конвертировать{*преобразовать*} значения к текущим параметрам настройки Модулей:

    void AsdkAcUiDialogSample::OnKillfocusEditAngle()

    {

    // Get and update text the user typed in.

    //

    m_ctrlAngleEdit.Convert();

    m_ctrlAngleEdit.GetWindowText(m_strAngle);

    }

    void AsdkAcUiDialogSample::OnKillfocusEditXpt()

    {

    // Get and update text the user typed in.

    //

    m_ctrlXPtEdit.Convert();

    m_ctrlXPtEdit.GetWindowText(m_strXPt);

    }

    void AsdkAcUiDialogSample::OnKillfocusEditYpt()

    {

    // Get and update text the user typed in.

    //

    m_ctrlYPtEdit.Convert();

    m_ctrlYPtEdit.GetWindowText(m_strYPt);

    }

    void AsdkAcUiDialogSample::OnKillfocusEditZpt()

    {

    // Get and update text the user typed in.

    //

    m_ctrlZPtEdit.Convert();

    m_ctrlZPtEdit.GetWindowText(m_strZPt);

    }

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

    void AsdkAcUiDialogSample::OnKillfocusComboRegapps()

    {

    CString strFromEdit;

    m_ctrlRegAppComboBox.GetWindowText(strFromEdit);


    if (m_ctrlRegAppComboBox.FindString(-1, strFromEdit) == CB_ERR)

    if (acdbRegApp(strFromEdit) == RTNORM)

    m_ctrlRegAppComboBox.AddString(strFromEdit);

    }

    7, чтобы делать некоторую проверку правильности данных, мы обрабатываем это в OnOk () обработчик. Это, конечно, может быть сделано в любое время. Также обратите внимание, что OnOk () обработчик сохраняет данные в параметр пользователя (системный реестр), используя SetDialogData () функция:

    void AsdkAcUiDialogSample::OnOK()

    {

    if (!ValidatePoint()) {

    AfxMessageBox("Sorry, Point out of desired range.");

    m_ctrlXPtEdit.SetFocus();

    return;

    }

    if (!ValidateAngle()) {

    AfxMessageBox("Sorry, Angle out of desired range.”);

    m_ctrlAngleEdit.SetFocus();

    return;

    }

    // Store the data into the registry

    //

    SetDialogData("ANGLE", m_strAngle);

    SetDialogData("POINTX", m_strXPt);

    SetDialogData("POINTY", m_strYPt);

    SetDialogData("POINTZ", m_strZPt);

    CAcUiDialog::OnOK();

    }

    8 Наконец, OnInitDialog () функция заботится о всей инициализации, включая изменение размеров и требования постоянства данных:

    BOOL AsdkAcUiDialogSample::OnInitDialog()

    {

    // Set the dialog name for registry lookup and storage

    //

    SetDialogName("AsdkAcUiSample:AsdkAcUiDialog");

    CAcUiDialog::OnInitDialog();

    DLGCTLINFOdlgSizeInfo[]= {

    { IDC_STATIC_GROUP1, ELASTICX, 20 },

    { IDC_STATIC_GROUP1, ELASTICY, 100 },

    { IDC_EDIT_XPT,ELASTICX, 20 },

    { IDC_EDIT_YPT,ELASTICX, 20 },

    { IDC_EDIT_ZPT,ELASTICX, 20 },

    { IDC_EDIT_ANGLE, ELASTICX, 20 },

    { IDC_STATIC_GROUP2, MOVEX, 20 },

    { IDC_STATIC_GROUP2, ELASTICY, 100 },

    { IDC_STATIC_GROUP2, ELASTICX, 80 },

    { IDC_LIST_BLOCKS, MOVEX, 20 },

    { IDC_LIST_BLOCKS, ELASTICY, 100 },

    { IDC_STATIC_TEXT2,MOVEX, 20 },

    { IDC_STATIC_TEXT2,MOVEY, 100 },

    { IDC_LIST_BLOCKS, ELASTICX, 80 },

    { IDC_STATIC_TEXT2,ELASTICX, 80 },

    { IDC_STATIC_GROUP3, MOVEY, 100 },

    { IDC_STATIC_GROUP3, ELASTICX, 20 },

    { IDC_COMBO_REGAPPS, MOVEY, 100 },


    { IDC_COMBO_REGAPPS, ELASTICX, 20 },

    { IDC_STATIC_TEXT3,MOVEY, 100 },

    { IDC_STATIC_TEXT3,ELASTICX, 20 },

    { IDOK,MOVEX, 100 },

    { IDCANCEL, MOVEX, 100 },

    };

    const DWORD numberofentries =

    sizeof dlgSizeInfo / sizeof DLGCTLINFO;

    SetControlProperty(dlgSizeInfo, numberofentries);

    // Must be within a 100-unit cube centered about 0,0,0.

    //

    m_ctrlXPtEdit.SetRange(-50.0, 50.0);

    m_ctrlYPtEdit.SetRange(-50.0, 50.0);

    m_ctrlZPtEdit.SetRange(-50.0, 50.0);

    // Must be between 0 and 90 degrees.

    //

    m_ctrlAngleEdit.SetRange(0.0, 90.0 /*(PI/2.0)*/);

    // Assign a title for the dialog.

    //

    SetWindowText("AcUiDialog Sample");

    // Load the default bitmaps.

    //

    m_ctrlPickButton.AutoLoad();

    m_ctrlAngleButton.AutoLoad();

    // Get and display the preserved data from the registry.

    //

    if (!GetDialogData("ANGLE", m_strAngle))

    m_strAngle = "0.0";

    if (!GetDialogData("POINTX", m_strXPt))

    m_strXPt = "0.0";

    if (!GetDialogData("POINTY", m_strYPt))

    m_strYPt = "0.0";

    if (!GetDialogData("POINTZ", m_strZPt))

    m_strZPt = "0.0";

    DisplayPoint();

    DisplayAngle();

    DisplayBlocks();

    DisplayRegApps();

    return TRUE; // return TRUE unless you set the focus to a control

    }

    Добавьте Поддержку Системного реестра и Новый Объект COM ATL

    1 Добавляют следующую функцию инициализации системного реестра к AsdkDesignCenterSamp.cpp. Эта функция основает системный реестр, основанный на ресурсах системного реестра, которые будут добавлены в более позднем шаге.
    void registerAppInfo(HINSTANCE hInstance)
    {
    USES_CONVERSION;
    HRESULT hRes = S_OK;
    CComPtr p;
    hRes = CoCreateInstance(CLSID_Registrar, NULL,
    CLSCTX_INPROC_SERVER, IID_IRegistrar, (void**)&p);
    if(SUCCEEDED(hRes))
    {
    // Get the AutoCAD Product key from the
    // registry into a CString.
    //
    CString csProdKey = acrxProductKey();
    // Use CStrings to obtain the authorization
    // stamp from the registry.
    //
    CString csPath = "SOFTWARE\\Autodesk\\AutoCAD\\R15.0\\";
    CString csStamp = csProdKey.Right(csProdKey.GetLength()
    - csPath.GetLength());
    _TCHAR szRegKey[_MAX_PATH];
    _tcscpy(szRegKey, csStamp);
    LPOLESTR pszId = T2OLE("AUTH");
    // do a runtime swap of the registry key value.
    //
    p->AddReplacement(pszId, T2OLE(szRegKey));
    _TCHAR szModule[_MAX_PATH];
    GetModuleFileName(hInstance, szModule, _MAX_PATH);
    LPCOLESTR szType = OLESTR("REGISTRY");
    LPOLESTR pszModule = T2OLE(szModule);
    // Pull the registry entries from the resource ID.
    //
    hRes = p->ResourceRegister(pszModule, IDR_REGISTRY1,
    szType);
    if(FAILED(hRes))
    AfxMessageBox("Error registering the app info.");
    }
    }
    2 Теперь добавляют новый Объект ATL, который поддержит интерфейс IAcDcContentView.
    В Visual C++, выберите Вставку, Новый Объект ATL. В диалоге выбирают Объекты и выбирают Простой Объект. Нажмите Next, и введите имя для Объекта ATL. Для этого примера, назовите это AsdkDcContent. Теперь выберите позицию табуляции Names, и щелчок поддерживает ISupportErrorInfo. Нажмите OK, чтобы создать объект.
    3 Затем мы должны добавить некоторую информацию системного реестра к секции ресурса проекта. Сначала создайте новый файл по имени AsdkDesignCenterSamp .rgs. Следующая распечатка должна быть изменена для вашего определенного проекта, где ID класса (CLSID) должен быть скопирован с вашего файла IDL. Используйте CLSID, который соответствует интерфейсу IAsdkDcContent. Так как они - значения GUID, они отличны для каждого нового проекта. Также для других проектов, Вы будете должны изменить секции расширений и также добавлять имя вашего определенного класса. Снова, этот пример использует AsdkDcContent.

    HKLM

    {

    NoRemove ’SOFTWARE’

    {

    NoRemove ’Autodesk’

    {

    NoRemove ’AutoCAD’

    {

    NoRemove ’R15.0’

    {

    NoRemove ’%AUTH%’

    {

    NoRemove ’AutodeskApps’

    {

    NoRemove ’AcadDC’

    {

    NoRemove ’Extensions’

    {

    ForceRemove ’.txt’

    {

    val CLSID = s ’{}’

    IconIndex = d ’0’

    }

    }

    NoRemove ’Applications’

    {

    ForceRemove ’AsdkDcContent’

    {

    ’Extensions’

    {

    .txt

    {

    val CLSID = s ’{}’

    val IconIndex = d ’0’

    }

    }

    CustomView = s ’Yes’

    }

    }

    }

    }

    }

    }

    }

    }

    }

    }

    Сохраните этот файл, и в Visual C++ приносят ResourceView вперед. Откройте распечатку ресурсов, и разверните узла “REGISTRY”. Правый щелчок и импорт файл системного реестра. Это должно дать ресурсу ID IDR_REGISTRY1, но если это делает не, переименуйте это так, чтобы это соответствовало запросу в registerAppInfo.

    Документ Блокировка

    Все документы должны быть блокированы, чтобы изменяться. Документы могут также быть блокированы, чтобы предотвратить код в других контекстах выполнения от изменения их временно. Документы не должны быть блокированы, чтобы исполнить, запрос (читает) операции, и они никогда не предотвращены от выполняющих операций запроса на других документах. Основной документ блокировка обработана автоматически для AutoCAD, командует, ObjectARX
    команды, и функции AutoLISP.
    Немодальный диалог и код инструментальной панели, и любые команды, которые должны разработать -сторону активный документ, должны вручную исполнить документ блокировка.
    Для более детальной информации относительно документа блокировка, см. “ Явный Документ Блокировка ” на странице 425.

    Документо-независимые базы данных

    Чтобы участвовать в отмене в AutoCAD, базы данных должны быть связаны с документом, потому что каждый документ имеет независимый стек отмены. Однако, эта особенность находится в прямом конфликте с потребностью загрузить базы данных, чей содержание предназначено, чтобы быть разделенным поперек документа сеансы редактирования. Другими словами, Вы должны решить между следующим два сценария для ваших побочных баз данных:
    §
    Связывают базу данных с определенным документом, и не позволяют редактирования этому с других сеансов редактирования, и возможно загружают DWG или DXF файл в множественные базы данных в течение каждого сеанса редактирования, который нуждается в этом.
    § Загружают DWG или DXF файл, чтобы совместно использовать это поперек сеансов редактирования, и не имеют никакой автоматической отмены для этого. Или не поддержите отмену для них во всем (прекрасно, если они только для чтения, или только модифицированный для фактического сохраняет, или находятся под контролем пересмотра), или быть очень осторожным при использовании отмены.
    В ObjectARX, прежний сценарий - значение по умолчанию. Всякий раз, когда инициирован новый образец AcDbDatabase, это связано с текущим документом.
    Это - одна из причин,  приложение должно изменить{*заменить*} текущий документ без того, чтобы активизировать новый документ.
    AcDbDatabase класс обеспечивает следующую функцию, которая отключает отмену базы данных и разрушает связь базы данных с  документом:
    void  disableUndoRecording(Adesk::Boolean disable);
    Любая AcDb уверенность относительно любых документо-определенных переменных системы примет встроенные значения по умолчанию для документо-независимых баз данных. Также, не имеется никакой потребности блокировать любые документы, чтобы обратиться к докумено-независимым базам данных.
    ОБРАТИТЕ ВНИМАНИЕ На разработчиков, кто думают относительно вызова независимого контроллера отмены от контроллеров отмены множественного документа, должен остаться знающий, что выполняющий отмену в данном документе может вести к несогласованности и коррупции. Например: База данных X имеет контроллер отмены, не связанный с любым документом. Модификации от Документируют,  сделаны к Базе данных X, тогда модификациями из Документа B, которые полагаются на объекты, созданные или изменяемые от Документа модификации. Теперь, отмена применяется в Документе A. Изменения{*замены*}, сделанные к Документу B будут разрушены.


    Домен{*область*}

    AutoCAD solids - контурные представления (часто упоминаемый как B-rep модели), состоят из коллекции топологических объектов связности и связал геометрические граничные объекты. Топологические объекты определены в AcBr библиотеке и описаны позже в этой главе, принимая во внимание, что геометрические объекты определены в AcGe библиотеке.
    Объекты, определенные или сгенерированные AcBr библиотекой постоянно находятся в трехмерном Евклидовом пространстве модели (E 3). Единственные исключения - геометрические объекты, определенные в двумерном пространстве{*пробеле*} параметра поверхности (типа кривых параметра и значений параметра).
    Вообще, только 2-разнообразный топологический домен{*область*} поддержан AcBr библиотекой. Особенности (которые являются геометрическими вырождениями) поддержаны, чтобы представить вершину конуса, но проводных тел и смешанной размерности solids (который может включать повисшие провода, и лица) не поддержаны; и при этом они не могут быть реализованы в AutoCAD.
    Общий неразнообразный домен{*область*} - надмножество 2-разнообразного домена{*области*}, и позволяет отличным твердым объемам касаться в единственных{*отдельных*} точках, кривых, или лицах; и позволяет любую комбинацию каркаса, листа, и твердых объектов. Следующие неразнообразные объекты поддержаны в соответствии с AutoCAD и AcBr библиотекой:
    §
    Два 2-разнообразного solids, объединенный по общедоступному краю или вершине
    § объект AcDbBody, содержащий единственное лицо
    Топологический объект может быть неограничен (то есть это не может иметь никакой более низкой размерной топологии ограничения) только в следующих случаях:
    § замкнутая поверхность, которая свойственно ограничена, и в u и v руководствах{*направлениях*} (типа полного тора или сферы), представлен лицом, которое не имеет никаких границ цикла.
    § замкнутая кривая, которая свойственно ограничена (типа полного круга или эллипса), представлен краем, который имеет совпадающее начало и конечную вершину.

    Ограничения

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

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

    Особенности (типа вершины конуса) карта к граням в AutoCAD и таким образом может использоваться, чтобы инициализировать AcBrEdge для специальной цели запроса для вершины, но нельзя делать запрос для геометрии кривой или использоваться, чтобы установить AcBrLoopEdgeTraverser. К ним можно также обращаться, используя AcBrLoopVertexTraverser, поскольку особенность соответствует единственной границе цикла лица.

    Также, как с указателями AcDbObject, объекты AcBr не могут использоваться, как только объект базы данных AutoCAD был закрыт в базе данных или идет из контекста; они не постоянны. Любое изменение к объекту базы данных будет помечено как eBrepChanged ошибка, если уровень проверок правильности не был установлен, чтобы игнорировать изменения базы данных. Из-контекста или закрытого объекта базы данных будет вообще заставлять Acad:: eNotInDatabase быть возвращенным.

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

    AcBr иерархия классов - подмножество ObjectARX иерархии классов, и определяет следующие классы:

    Домен{*область*}

    Обратите внимание, что объекты AcBr не получены из AcDbObject, и поэтому не могут быть зарегистрированы с базой данных AutoCAD.

    Доступ к базам данных, связанным с нетекущими документами

    Иногда Вы будете должны смотреть или изменить базы данных, связанные с другими документами, но не нуждаться в любом явном вводе пользователя в них. Вы могли бы даже смотреть на кое-что связанное с другим документом.
    Чтобы просто исследовать базы данных, связанные с другими документами, Вы не должны блокировать документ, хотя, если документ блокирован в AcAp:: kXWrite режиме другим контекстом выполнения, Вы будете лишены доступа к любому из его элементов.
    Чтобы изменять базы данных, связанные другими документами, или предотвращать другие контексты выполнения от изменения их на некоторое время, Вы должны блокировать документ, определяя AcAp::kXWrite, AcAp::kWrite, или AcAp::kRead, в зависимости от вашего намерения. Если командный процессор документа не статический, это обычно уже блокируется, и если это взаимно исключает вашу блокировку, Вы будете лишены доступа.
    ОБРАТИТЕ ВНИМАНИЕ При изменении объектов базы данных в нетекущем документе, если Вы должны использовать сделки, убедитесь, что использовали операционного менеджера, связанного с документом.
    Такие модификации не будут невыполнимые из текущего документа. Вместо этого они будут зарегистрированы со стеком отмены их ведущего документа, и уничтожены,  используя отмену, когда ведущий документ текущий.Когда закончено с информацией, связанной с документом, убедитесь, что разблокировали это как можно скорее, минимизировали потенциал для конфликтов с другими командами.

    Доступ к таблицам идентификаторов

    AcdbTblNext() функция последовательно просматривает входы таблицы идентификаторов, и acdbTblSearch () функция возвращает определенные входы. Названия{*имена*} Таблицы определены строками. Допустимыеимена - “LAYER”, “LTYPE”, “VIEW”, “STYLE”, “BLOCK”, “UCS”, “VPORT”, and “APPID”. Обе из этих функций возвращают входы как списки буфера результата с кодами группы DXF.
    Первый запрос к acdbTblNext() возвращает первый вход в указанной таблице.
    Последующее звонит, которые определяют, что  та же самая таблица возвращает последовательные входы, если второй параметр к acdbTblNext() (перемотка) не отличный от нуля, когда acdbTblNext() возвращает первый вход снова.
    В следующем примере, функция getblock() возвращает первый блок (если любой) в текущем рисунке, и вызывает printdxf() функцией, чтобы отобразить содержание того блока в формате списка.
    void getblock()
    {
    struct resbuf *bl, *rb;
    bl = acdbTblNext("BLOCK", 1); // First entry
    acutPrintf("\nResults from getblock():\n");
    // Print items in the list as "assoc" items.
    for (rb = bl; rb != NULL; rb = rb->rbnext)
    printdxf(rb);
    // Release the acdbTblNext list.
    acutRelRb(bl);
    }
    Входы, отысканные в таблице БЛОКОВ, содержат группа  -2, которая содержит имя первого примитива на блочном определении. В рисунке к одиночному блоку по имени ПОЛЕ, запрос к getblock () печатает следующий (значение имени изменяется от сеанса до сеанса):
    Результаты от getblock ():
    (0 . "BLOCK")
    (2 . "BOX")
    (70 . 0)
    (10 9.0 2.0 0.0)
    (-2 . )
    Первый параметр к acdbTblSearch () - строка, которая называет таблицу, но второй параметр - строка, которая называет специфический символ в таблице. Если символ найден, acdbTblSearch () возвращает его данные. Эта функция имеет третий параметр, setnext, который может использоваться, чтобы координировать операции с acdbTblNext (). Если setnext нулевой, acdbTblSearch () запрос не имеет никакого эффекта на acdbTblNext (), но если setnext отличный от нуля, следующий запрос к acdbTblNext () возвращает вход таблицы, который следует за входом, найденным acdbTblSearch ().

    Setnext опция особенно полезна, когда имеющий дело с VPORT таблицей идентификаторов, потому что все области просмотра в специфической конфигурации области просмотра имеют то же самое имя (типа *ACTIVE).

    Имейте в виду, что, если к  VPORT таблице идентификаторов обращаются, когда TILEMODE выключен, изменения{*замены*} не имеют никакого видимого эффекта, пока TILEMODE не поворачивает обратно на. (TILEMODE установлен или командой SETVAR или,  вводя ее имя непосредственно.) Не путают VPORT таблицу идентификаторов с примитивами области просмотра.

    Чтобы находить и обрабатывать каждую область просмотра в конфигурации, названной 4VIEW, Вы могли бы использовать следующий код:

    struct resbuf *v, *rb;

    v = acdbTblSearch("VPORT", "4VIEW", 1);

    while (v != NULL} {

    for (rb = v; rb != NULL; rb = rb->rbnext)

    if (rb->restype == 2)

    if (strcmp(rb->resval.rstring, "4VIEW") == 0) {

    .// Process the VPORT entry

    .

    .

    acutRelRb(v);

    // Get the next table entry.

    v = acdbTblNext("VPORT", 0);

    } else {

    acutRelRb(v);

    v = NULL; // Break out of the while loop.

    break; // Break out of the for loop.

    }

    }

    Доступ к текущему документу и связанным с ним объектам

    Ключ вызывает ObjectARX-приложение, должен делать, когда это извлекает пользу, контроль должен выяснить текущий документ, который может быть выполнен с функцией acDocManager->curDocument().
    ОБРАТИТЕ ВНИМАНИЕ, что  текущий документ - не всегда активный документ. Дело обстоит так в течение переходных состояний, типа того, когда documentToBeActivated () реактор происходит. Не делайте попытку обширной обработки в течение переходных состояний.
    Рассмотрите использование mdiActiveDocument () если Вы заинтересованы активным документом.
    Из текущего документа, Вы можете определять текущую базу данных, уместного операционного менеджера, и связанное определенное документом состояние вашего приложения, и затем делать любые потребности, которые будут сделаны перед возвращением.
    Как только команда сохранила текущий документ и связала информацию относительно ее стека, не требоваться сделать запрос текущего документа снова до завершения. Всякий раз, когда подсказка для ввода пользователя сделана, пользователь может переключать документы, но если это сделано, текущая команда приостановлена, и ее состояние стека сохранено, пока документ не оживлен.
    Если ваше приложение работает от прикладного контекста выполнения, это должно блокировать и разблокировать текущий документ, чтобы изменить что - нибудь связанное этим. Это может делать так,  непосредственно вызывая AcApDocManager::lockDocument () и unlockDocument () функцию члена.
    Если ваше приложение работает от функции ObjectARX или AutoLISP, никакая блокировка не должна быть необходима, поскольку система устанавливает блокировки и удаляет их автоматически вокруг выражений AutoLISP и команд.

    Другие соображения по прикладному контексту выполнения

    Имеются также некоторые возможности и ограничения, которые применяются к коду, выполняющему в прикладном контексте выполнения.
    §
    когда контекст выполнения ваш код выполняется под,  не неявен в вашей структуре кода, Вы можете делать этот запрос, чтобы найти,является ли это прикладной контекст выполнения:
    Adesk::Boolean
    AcApDocManager::isApplicationContext() const;
    § Все ActiveX члены ввода пользователя может использоваться, но удостовериться, что Вы вызываете их на сервисный объект, связанный с активным и текущим документом. Как отмечено выше, переключение документа будет заблокировано, когда ввод пользователя получен в этом контексте. Вы можете получить IACADDOCUMENT* образец, который соответствует потоку AcApDocument через запрос:
    acDocManager()->curDocument()->cDoc()->GetIDispatch( BOOL bAddRef);
    § Все ObjectARX функции ввода пользователя может быть вызван с текущим активным документом,  неявно используемым. Как отмечено выше, переключение документа будет заблокировано, когда ввод пользователя получен в этом контексте.
    § Прикладной код, выполняющийся от прикладного контекста может использовать следующую функцию члена, чтобы переключить или текущий и активный документ, вместе или индивидуально, как желательно.
    virtual Acad::ErrorStatus
    setCurDocument(
    AcApDocument* pDoc,
    AcAp::DocLockMode = AcAp::kNone,
    bool activate = false) = 0;
    § чередуясь между запросом ввода пользователя и изменения или формирования текущего документа, можно запрашивать относительно ввода от множественных документов от единственного контекста выполнения и единственной последовательности кода. Недостаток{*препятствие*} - то переключение документа пользователем,  заблокирован при запросе ввода, так что код должен знать, к которому документу требуется переключить.
    § когда активные и текущие документы отличаются, знать что ActiveX и ObjectARX ввод пользователя функции не будет работать должным образом. Используйте curDocument () и mdiActiveDocument () функции, чтобы проверить текущие и активные документы.
    § если приложение выгружается с текущим документом и активным отличным документом, следующее входное событие восстановит текущий документ назад к активному документу.
    § когда код, выполняющийся от прикладного контекста запрашивает ввод пользователя, используя ActiveX функции ввода пользователя, автоматическое интерактивное переключение документа заблокирован, хотя текущее переключение документа может быть выполнено.

    Дуга

    CircularArc () функция имеет две формы:
    virtual Adesk::Boolean
    AcGiWorldGeometry::circularArc(
    const AcGePoint3d& center,
    const double radius,
    const AcGeVector3d& normal,
    const AcGeVector3d& startVector,
    const double sweepAngle,
    const AcGiArcType arcType = kAcGiArcSimple) const = 0;
    virtual Adesk::Boolean
    AcGiWorldGeometry::circularArc(
    const AcGePoint3d& start,
    const AcGePoint3d& point,
    const AcGePoint3d& end,
    const AcGiArcType arcType = kAcGiArcSimple) const = 0;
    Переменная типа дуги, AcGiArcType, может иметь одно из следующих значений:
    § kAcGiArcSimple Дуга непосредственно, которая - не fillable
    § kAcGiArcSector   Область, ограниченная дугой и ее центром искривления
    § kAcGiArcChord   Область, ограниченная дугой и ее конечными точками
    Дуга

    Двумерные соты (Tessellation)

    Кривые и кривые поверхности должны быть мозаичным —, разбитым в линии и многоугольники —, чтобы быть отображенными. Градус{*степень*} двумерных сот определяет насколько точный отображенная кривая будет (как близко это приблизит математическую “истинную” кривую) и сколько работы наверху требовано, чтобы генерировать графику для кривой. Очень маленький круг может требовать только, чтобы единственный пиксел отобразил это. Большой круг может требовать сотен маленьких долей линии, которые будут рассчитаны и отображен, чтобы создать гладкое появление.
    deviation() функции, обеспеченные AcGiWorldDraw и классами AcGiViewportDraw возвращают отклонение, которое является допустимым максимальным различием в мировом пространстве между истинной математической поверхностью и мозаичной поверхностью, как показано в следующем рисунке:
    Двумерные соты (Tessellation)
    Обратитесь к этому значению, позволяет заказным примитивам настраивать их двумерные соты к энергии команды VIEWRES процент на опцию, которая установлена пользователем. Результат - то, что заказные примитивы являются мозаичными к относительно та же самая гладкость как встроенные примитивы.
    deviation () функция возвращает предложенное максимальное отклонение в мировом пространстве, учитывая тип отклонения, чтобы вычислить и точку в мировом пространстве для перспективного масштабирования если требовано. Сигнатура для deviation() функция
    virtual double
    AcGiWorldDraw::deviation(
    AcGiDeviationType
    devType,
    const AcGePoint3d&) const = 0;
    Типы отклонения
    § kAcGiMaxDevForCircle (для кругов и дуг)
    § kAcGiMaxDevForCurve
    § kAcGiMaxDevForBoundary
    § kAcGiMaxDevForIsoline
    § kAcGiMaxDevForFacet (для поверхностей; формула для вычисления этого отклонения использует значение FACETRES переменной системы)

    DwgIn () Функция

    DwgIn () функция, которая вызывает dwgInFields (), вызван следующими командами и условиями{*состояниями*}:
    §
    OPEN (использует kFileFiler)
    § UNDO (использует kUndoFiler)
    § INSERT, COPY, XREF (используйте kDeepCloneFiler и kIdXlateFiler)
    § WBLOCK (использует kWblockCloneFiler и kIdXlateFiler)
    § Любое время объект просматривается в (использует kPageFiler)

    DwgOut () Функция

    DwgOut () функция, которая вызывает{*называет*} dwgOutFields (), вызван следующими командами и условиями{*состояниями*}:
    § SAVE (uses kFileFiler)
    § SAVEAS (uses kFileFiler)
    § WBLOCK (uses kWblockCloneFiler and kIdXlateFiler)
    § INSERT, XREF (use kDeepCloneFiler and kIdXlateFiler)
    § COPY (использует тех же самых регистраторов как INSERT; копия требует записывающий состояние объекта и затем чтения этому назад в к объекту того же самого класса)
    § PURGE (uses a kPurgeFiler)
    § Любое время объект просматривается из (использует kPageFiler)
    § Любое время объект изменяется (для регистрации отмены; использует kUndoFiler)

    DXF Коды Группы для Xrecords

    Следующая таблица перечисляет коды группы DXF, которые могут использоваться в records.
    Диапазоны кодов DXF-групп для xrecords

    From
    To
    DataType
    1
    4
    Text
    6
    9
    Text
    10
    17
    Point or vector (3 reals)
    38
    59
    Real
    60
    79
    16-bit integer
    90
    99
    32-bit integer
    102
    102
    Control string “{“ or “}”
    140
    149
    real
    170
    179
    16-bit integer
    210
    219
    Real
    270
    279
    16-bit integer
    280
    289
    8-bit integer
    300
    309
    Text
    310
    319
    Binary chunk
    320
    329
    Handle
    330
    339
    Soft pointer ID
    340
    349
    Hard pointer ID
    350
    359
    Soft ownership ID
    360
    369
    Hard ownership ID

    Для описания жестких и мягких владельцев и указателей, см. главу 12, “ Происходящий от AcDbObject. ”

    DXF Коды Группы

    Много функций ObjectARX возвращают коды типа, определенные в предшествующей таблице. Однако, в результатах от функций, которые обрабатывают, примитивы, restype поле содержат коды группы DXF, которые описаны в Руководстве Настройки AutoCAD. Например, в списке примитива, restype поле 10 указывает точку, в то время как restype 41 указывает реальное значение.
    Рисунки AutoCAD состоят из структурных контейнеров для объектов базы данных, имеющих следующие компоненты:
    §
    уникальная метка, которая всегда позволяется и это сохраняется продолжении жизни рисунка
    § необязательный список xdata
    § необязательный набор постоянных реакторов
    § необязательный указатель монопольного использования на словарь расширения, который имеет другие объекты базы данных, помещенные в это приложением
    Объекты Базы данных - объекты без уровня, linetype, цвета, или любых других геометрических или графических свойств, и примитивы получены из объектов и имеют геометрические и графические свойства.
    Поскольку коды DXF - всегда меньше чем 2,000, и коды типа результата всегда большие, приложение может легко определять, когда список буфера результата содержит значения результата (как возвращено acedGetArgs (), например) или содержит данные определения примитива (как возвращено acdbEntGet () и другими функциями примитива).
    Следующий рисунок показывает формат буфера результата круга, отысканного acdbEntGet ():
    DXF Коды Группы
    Следующий типовой кодовый фрагмент показывает функцию, dxftype (), который пропускают код группы DXF и связанный примитив, и возвращает соответствующий код типа. Код типа указывает то, что тип данных может представлять данные: RTREAL указывает,  с двойной точностью с плавающей точкой значение, RT3DPOINT указывает ads_point, и так далее. Вид примитива (например, нормальный примитив типа круга, блочного определения, или входа таблицы типа области просмотра) обозначен определениями типов, которые сопровождают эту функцию:

    #define ET_NORM 1 // Normal entity

    #define ET_TBL 2 // Table

    #define ET_VPORT 3 // Table numbers

    #define ET_LTYPE 4

    #define ET_LAYER 5

    #define ET_STYLE 6

    #define ET_VIEW 7

    #define ET_UCS 8

    #define ET_BLOCK 9

    // Get basic C- language type from AutoCAD DXF group code (RTREAL,

    // RTANG are doubles, RTPOINT double[2], RT3DPOINT double[3],

    // RTENAME long[2]). The etype argument is one of the ET_

    // definitions.

    //

    // Returns RTNONE if grpcode isn’t one of the known group codes.

    // Also, sets "inxdata" argument to TRUE if DXF group is in XDATA.

    short dxftype(short grpcode, short etype, int *inxdata)

    {

    short rbtype = RTNONE;

    *inxdata = FALSE;

    if (grpcode >= 1000) { // Extended data (XDATA) groups

    *inxdata = TRUE;

    if (grpcode == 1071)

    rbtype = RTLONG; // Special XDATA case

    else

    grpcode %= 1000; // All other XDATA groups match.

    } // regular DXF code ranges

    if (grpcode <= 49) {

    if (grpcode >= 20) // 20 to 49

    rbtype = RTREAL;

    else if (grpcode >= 10) { // 10 to 19

    if (etype == ET_VIEW) // Special table cases

    rbtype = RTPOINT;

    else if (etype == ET_VPORT && grpcode <= 15)

    rbtype = RTPOINT;

    else // Normal point

    rbtype = RT3DPOINT; // 10: start point, 11: endpoint

    }

    else if (grpcode >= 0) // 0 to 9

    rbtype = RTSTR; // Group 1004 in XDATA is binary

    else if (grpcode >= -2)

    // -1 = start of normal entity -2 = sequence end, etc.

    rbtype = RTENAME;

    else if (grpcode == -3)

    rbtype = RTSHORT; // Extended data (XDATA) sentinel

    }

    else {

    if (grpcode <= 59) // 50 to 59

    rbtype = RTANG; // double

    else if (grpcode <= 79) // 60 to 79

    rbtype = RTSHORT;

    else if (grpcode < 210)

    ;

    else if (grpcode <= 239) // 210 to 239

    rbtype = RT3DPOINT;

    else if (grpcode == 999) // Comment

    rbtype = RTSTR;

    }

    return rbtype;

    }

    Приложение получает список буфера результата (вызвал rb), представляя вход в таблице идентификаторов области просмотра, и следующая инструкция C вызывает dxftype ():

    Ctype = dxftype (rb-

    > restype, ET_VPORT, &inxdata);

    Предположим, что rb- >restype равняется 10. Тогда dxftype() возвращает RTPOINT, указывая, что примитив является двумерной точкой, чьи координаты (типа ads_real) находятся в rb->resval.rpoint [X] и rb->resval.rpoint [Y].

    DxfIn () Функция

    DxfIn () функция, которая вызывает{*называет*} dxfInFields (), вызван следующим
    Команды и функции:
    §
    OPEN
    § INSERT
    § acdbEntMod() или acdbEntMake()

    DxfOut () Функция

    DxfOut () функция, которая вызывает{*называет*} dxfOutFields (), вызван следующими командами и функциями:
    § WBLOCK
    § SAVE
    § SAVEAS
    § acdbEntGet ()

    Файл реализации

    Следующий код показывает выполнению для нового класса AsdkMyClass:
    ACRX_DXF_DEFINE_MEMBERS(AsdkMyClass, AcDbObject,
    AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent, 0,
    ASDKMYCLASS, SAMP2);
    // Gets the value of the integer data member.
    //
    Acad::ErrorStatus
    AsdkMyClass::getData(Adesk::Int16& val)
    {
    // Tells AutoCAD a read operation is taking place.
    //
    assertReadEnabled();
    val = mIntval;
    return Acad::eOk;
    }
    // Sets the value of the integer data member.
    //
    Acad::ErrorStatus
    AsdkMyClass::setData(Adesk::Int16 val)
    {
    // Triggers openedForModify notification.
    //
    assertWriteEnabled();
    mIntval = val;
    return Acad::eOk;
    }
    // Files data in from a DWG file.
    //
    Acad::ErrorStatus
    AsdkMyClass::dwgInFields(AcDbDwgFiler* pFiler)
    {
    assertWriteEnabled();
    AcDbObject::dwgInFields(pFiler);
    // For wblock filing we wrote out our owner as a hard
    // pointer ID so now we need to read it in to keep things
    // in sync.
    //
    if (pFiler->filerType() == AcDb::kWblockCloneFiler) {
    AcDbHardPointerId id;
    pFiler->readItem(&id);
    }
    pFiler->readItem(&mIntval);
    return pFiler->filerStatus();
    }
    // Files data out to a DWG file.
    //
    Acad::ErrorStatus
    AsdkMyClass::dwgOutFields(AcDbDwgFiler* pFiler) const
    {
    assertReadEnabled();
    AcDbObject::dwgOutFields(pFiler);
    // Since objects of this class will be in the Named
    // Objects Dictionary tree and may be hard referenced
    // by some other object, to support wblock we need to
    // file out our owner as a hard pointer ID so that it
    // will be added to the list of objects to be wblocked.
    //
    if (pFiler->filerType() == AcDb::kWblockCloneFiler)
    pFiler->writeHardPointerId((AcDbHardPointerId)ownerId());
    pFiler->writeItem(mIntval);
    return pFiler->filerStatus();
    }
    // Files data in from a DXF file.
    //
    Acad::ErrorStatus
    AsdkMyClass::dxfInFields(AcDbDxfFiler* pFiler)
    {
    assertWriteEnabled();
    Acad::ErrorStatus es;
    if ((es = AcDbObject::dxfInFields(pFiler)) != Acad::eOk)
    {
    return es;

    }

    // Check if we’ re at the right subclass getData marker.

    //

    if (!pFiler->atSubclassData("AsdkMyClass")) {

    return Acad::eBadDxfSequence;

    }

    struct resbuf inbuf;

    while (es == Acad::eOk) {

    if ((es = pFiler->readItem(&inbuf)) == Acad::eOk) {

    if (inbuf.restype == AcDb::kDxfInt16) {

    mIntval = inbuf.resval.rint;

    }

    }

    }

    return pFiler->filerStatus();

    }

    // Files data out to a DXF file.

    //

    Acad::ErrorStatus

    AsdkMyClass::dxfOutFields(AcDbDxfFiler* pFiler) const

    {

    assertReadEnabled();

    AcDbObject::dxfOutFields(pFiler);

    pFiler->writeItem(AcDb::kDxfSubclass, "AsdkMyClass");

    pFiler->writeItem(AcDb::kDxfInt16, mIntval);

    return pFiler->filerStatus();

    }

    // This function creates two objects of class AsdkMyClass.

    // It fills them in with the integers 1 and 2, and then adds

    // them to the dictionary associated with the key ASDK_DICT.

    // If this dictionary doesn’t exist, it is created and added

    // to the named object dictionary.

    //

    void

    createDictionary()

    {

    AcDbDictionary *pNamedobj;

    acdbHostApplicationServices()->workingDatabase()->

    getNamedObjectsDictionary(pNamedobj, AcDb::kForWrite);

    // Check to see if the dictionary we want to create is

    // already present. If not, create it and add

    // it to the named object dictionary.

    //

    AcDbDictionary *pDict;

    if (pNamedobj->getAt("ASDK_DICT", (AcDbObject*&) pDict,

    AcDb::kForWrite) == Acad::eKeyNotFound)

    {

    pDict = new AcDbDictionary;

    AcDbObjectId DictId;

    pNamedobj->setAt("ASDK_DICT", pDict, DictId);

    }

    pNamedobj->close();

    if (pDict) {

    // Create new objects to add to the new dictionary,

    // add them, then close them.

    //

    AsdkMyClass *pObj1 = new AsdkMyClass(1);

    AsdkMyClass *pObj2 = new AsdkMyClass(2);

    AcDbObjectId rId1, rId2;

    pDict->setAt("OBJ1", pObj1, rId1);

    pDict->setAt("OBJ2", pObj2, rId2);

    pObj1->close();

    pObj2->close();

    pDict->close();

    }

    }

    // Opens the dictionary associated with the key ASDK_DICT


    // and iterates through all its entries, printing out the

    // integer data value in each entry.

    //

    void

    iterateDictionary()

    {

    AcDbDictionary *pNamedobj;

    acdbHostApplicationServices()->workingDatabase()

    ->getNamedObjectsDictionary(pNamedobj, AcDb::kForRead);

    // Get a pointer to the ASDK_DICT dictionary.

    //

    AcDbDictionary *pDict;

    pNamedobj->getAt("ASDK_DICT", (AcDbObject*&)pDict, AcDb::kForRead);

    pNamedobj->close();

    // Get an iterator for the ASDK_DICT dictionary.

    //

    AcDbDictionaryIterator* pDictIter= pDict->newIterator();

    AsdkMyClass *pMyCl;

    Adesk::Int16 val;

    for (; !pDictIter->done(); pDictIter->next()) {

    // Get the current record, open it for read, and

    // print its data.

    //

    pDictIter->getObject((AcDbObject*&)pMyCl,

    AcDb::kForRead);

    pMyCl->getData(val);

    pMyCl->close();

    acutPrintf("\nintval is: %d", val);

    }

    delete pDictIter;

    pDict->close();

    }

    // The initialization function called from the acrxEntryPoint()

    // function during the kInitAppMsg case is used to add commands

    // to the command stack and to add classes to the ACRX class

    // hierarchy.

    //

    void

    initApp()

    {

    acedRegCmds->addCommand("ASDK_DICTIONARY_COMMANDS",

    "ASDK_CREATE", "CREATE", ACRX_CMD_MODAL,

    createDictionary);

    acedRegCmds->addCommand("ASDK_DICTIONARY_COMMANDS",

    "ASDK_ITERATE", "ITERATE", ACRX_CMD_MODAL,

    iterateDictionary);

    AsdkMyClass::rxInit();

    acrxBuildClassHierarchy();

    }

    // The cleanup function called from the acrxEntryPoint() function

    // during the kUnloadAppMsg case removes this application’s

    // command set from the command stack and removes this application’s

    // custom classes from the ACRX runtime class hierarchy.

    //

    void

    unloadApp()

    {

    acedRegCmds->removeGroup("ASDK_DICTIONARY_COMMANDS");

    // Remove the AsdkMyClass class from the ACRX runtime

    // class hierarchy. If this is done while the database is

    // still active, it should cause all objects of class

    // AsdkMyClass to be turned into proxies.

    //

    deleteAcRxClass(AsdkMyClass::desc());

    }

    Файл Заголовка

    Следующий код показывает объявлению класса для нового класса AsdkMyClass полученный из AcDbObject.
    class AsdkMyClass : public AcDbObject
    //
    // This class demonstrates custom objects.
    //
    // To keep it simple, this class has a single integer data
    // member. Get and set functions are provided for this
    // data member.
    //
    {
    public:
    ACRX_DECLARE_MEMBERS(AsdkMyClass);
    AsdkMyClass(): mIntval(0) {};
    AsdkMyClass(const Adesk::Int16& val): mIntval(val) {};
    Acad::ErrorStatus getData (Adesk::Int16&);
    Acad::ErrorStatus setData (Adesk::Int16);
    virtual Acad::ErrorStatus dwgInFields (AcDbDwgFiler*);
    virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler*)
    const;
    virtual Acad::ErrorStatus dxfInFields (AcDbDxfFiler*);
    virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler*)
    const;
    private:
    Adesk::Int16 mIntval;
    };

    Файлы Заголовка

    Следующие файлы заголовка должны быть включены в источник ObjectARX-приложения file:


    Adesk.h

    Содержит стандартные определения для среды программы ObjectARX.

    Rxdefs.h

    Устанавливает ObjectARX-приложение и взаимодействует с AutoCAD через acrxEntryPoint ().

    Adslib.h

    Устанавливает платформа-определенные определения и включает adscodes.h и ads.h.

    Adscodes.h

    Содержит определения значений кода, которые возвращены (или проходят к) библиотечные функции ADS.

    Ads.h

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

    Adsdlg.h

    Содержит Контроль Диалога Связанные языком объявления для создания диалоговых окон.

    Ol_errno.h

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

    Adsdef.h

    Устанавливает определения для среды программы ADS.

     Adslib.h файл заголовка содержит директивы для включения adscodes.h, adsdef.h, и ads.h; поэтому, прикладной исходный файл должен содержать только следующую директиву:
     #include "Adslib.h"
    ObjectARX-приложение не должно включить ol_errno.h, если это не использует символические коды, определенные там, чтобы обработать значение ERRNO. Приложение не должно включить adsdlg.h, если это не создает диалоговые окна.

    Фильтр Точки ввода и Пример Монитора

    Следующий пример демонстрирует использование фильтров точки ввода и мониторов.
    #include "adslib.h"
    #include "aced.h’
    #include "dbmain.h"
    #include "acdbabb.h"
    #include "adeskabb.h"
    #include "rxregsvc.h"
    #include "acgi.h"
    #include "acdocman.h"
    #include "acedinpt.h"
    #include "dbapserv.h"
    class IPM : public AcEdInputPointMonitor
    {
    public:
    virtual Acad::ErrorStatus
    monitorInputPoint(
    // Output. If changedTooltipStr is kTrue, newTooltipString
    // has the new ToolTip string in it.
    //
    bool& appendToTooltipStr,
    char*& additionalTooltipString,
    // Input/Output
    //
    AcGiViewportDraw* drawContext,
    // Input parameters:
    //
    AcApDocument* document,
    bool pointComputed,
    int history,
    const AcGePoint3d& lastPoint,
    const AcGePoint3d& rawPoint,
    const AcGePoint3d& grippedPoint,
    const AcGePoint3d& cartesianSnappedPoint,
    const AcGePoint3d& osnappedPoint,
    AcDb::OsnapMask osnapMasks,
    // const AcArray& customOsnapModes
    const AcArray& apertureEntities,
    const AcArray< AcDbObjectIdArray,
    AcArrayObjectCopyReallocator< AcDbObjectIdArray > >&
    nestedPickedEntities,
    int gsSelectionMark,
    const AcArray& keyPointEntities,
    const AcArray& alignmentPaths,
    const AcGePoint3d& computedPoint,
    const char* tooltipString);
    };
    Acad::ErrorStatus
    IPM::monitorInputPoint(
    // Output. If changedTooltipStr is kTrue, then newTooltipString
    // has the new ToolTip string in it.
    //
    bool& appendToTooltipStr,
    char*& additionalTooltipString,
    // Input/Output
    //
    AcGiViewportDraw* pDrawContext,
    // Input parameters:
    //
    AcApDocument* document,
    bool pointComputed,
    int history,
    const AcGePoint3d& lastPoint,
    const AcGePoint3d& rawPoint,
    const AcGePoint3d& grippedPoint,
    const AcGePoint3d& cartesianSnappedPoint,

    const AcGePoint3d& osnappedPoint,

    AcDb::OsnapMask osnapMasks,

    // const AcArray& customOsnapModes

    const AcArray& apertureEntities,

    const AcArray< AcDbObjectIdArray,

    AcArrayObjectCopyReallocator< AcDbObjectIdArray > >&

    nestedPickedEntities,

    int gsSelectionMark,

    const AcArray& keyPointEntities,

    const AcArray& alignmentPaths,

    const AcGePoint3d& computedPoint,

    const char* tooltipString)

    {

    acutPrintf("\nhistory: %d\n", history);

    if (pointComputed)

    {

    acutPrintf(

    "rawPoint: %.2f, %.2f, %.2f\n",

    rawPoint[0],

    rawPoint[1],

    rawPoint[2]);

    if (history & Acad::eGripped)

    acutPrintf(

    "grippedPoint: %.2f, %.2f, %.2f\n",

    grippedPoint[0],

    grippedPoint[1],

    grippedPoint[2]);

    if (history & Acad::eCartSnapped)

    acutPrintf(

    "cartesianSnappedPoint: %.2f, %.2f, %.2f\n",

    cartesianSnappedPoint[0],

    cartesianSnappedPoint[1],

    cartesianSnappedPoint[2]);

    if (history & Acad::eOsnapped)

    {

    acutPrintf(

    "osnappedPoint: %.2f, %.2f, %.2f\n",

    osnappedPoint[0],

    osnappedPoint[1],

    osnappedPoint[2]);

    #define OSMASK_CHECK(x) if (osnapMasks & AcDb:: ## x)

    acutPrintf("%s ", #x)

    OSMASK_CHECK(kOsMaskEnd);

    OSMASK_CHECK(kOsMaskMid);

    OSMASK_CHECK(kOsMaskCen);

    OSMASK_CHECK(kOsMaskNode);

    OSMASK_CHECK(kOsMaskQuad);

    OSMASK_CHECK(kOsMaskInt);

    OSMASK_CHECK(kOsMaskIns);

    OSMASK_CHECK(kOsMaskPerp);

    OSMASK_CHECK(kOsMaskTan);

    OSMASK_CHECK(kOsMaskNear);

    OSMASK_CHECK(kOsMaskQuick);

    OSMASK_CHECK(kOsMaskApint);

    OSMASK_CHECK(kOsMaskImmediate);

    OSMASK_CHECK(kOsMaskAllowTan);

    OSMASK_CHECK(kOsMaskDisablePerp);

    OSMASK_CHECK(kOsMaskRelCartesian);

    OSMASK_CHECK(kOsMaskRelPolar);

    #undef OSMASK_CHECK

    acutPrintf("\n");

    }

    acutPrintf("%d apertureEntities: ",  apertureEntities.length());

    for (int i = 0; i < apertureEntities.length(); i++)

    acutPrintf("<%x> ", apertureEntities[i].asOldId());


    acutPrintf("\n");

    }

    else {

    acutPrintf("No point computed");

    if (history & Acad::eCyclingPt)

    acutPrintf(", but new cycling osnap: %.2f, %.2f, %.2f\n",

    osnappedPoint[0], osnappedPoint[1], osnappedPoint[2]);

    else

    acutPrintf(".\n");

    }

    if (NULL != pDrawContext)

    {

    pDrawContext->subEntityTraits().setColor(2);

    pDrawContext->geometry().circle(rawPoint, 1.0,

    AcGeVector3d::kZAxis);

    }

    else

    acutPrintf("ViewportDraw is NULL!\n");

    if (history & Acad::eNotDigitizer)

    acutPrintf("PICK!\n");

    if (NULL != tooltipString)

    {

    acutPrintf("TooltipString: %s\n", tooltipString);

    additionalTooltipString = ", anotherString!";

    appendToTooltipStr = true;

    }

    if (history & Acad::eOrtho)

    {

    acutPrintf("Ortho found at %.2f, %.2f, %.2f\n",

    computedPoint[0], computedPoint[1], computedPoint[2]);

    }

    return Acad::eOk;

    }

    class IPF : public AcEdInputPointFilter {

    public:

    Acad::ErrorStatus

    processInputPoint(

    bool& changedPoint,

    AcGePoint3d& newPoint,

    bool& changedTooltipStr,

    char*& newTooltipString,

    bool& retry,

    AcGiViewportDraw* pDrawContext,

    AcApDocument* document,

    bool pointComputed,

    int history,

    const AcGePoint3d& lastPoint,

    const AcGePoint3d& rawPoint,

    const AcGePoint3d& grippedPoint,

    const AcGePoint3d& cartesianSnappedPoint,

    const AcGePoint3d& osnappedPoint,

    AcDb::OsnapMask osnapMasks,

    // const AcArray& customOsnapModes

    const AcArray& pickedEntities,

    const AcArray< AcDbObjectIdArray,

    AcArrayObjectCopyReallocator< AcDbObjectIdArray > >&

    nestedPickedEntities,

    // Of 0th element in pickedEntities.

    int gsSelectionMark,

    // AutoSnap Info:

    const AcArray& keyPointEntities,

    const AcArray& alignmentPaths,

    const AcGePoint3d& computedPoint,

    const char* tooltipString);

    };

    Acad::ErrorStatus


    IPF::processInputPoint(

    bool& changedPoint,

    AcGePoint3d& newPoint,

    bool& changedTooltipStr,

    char*& newTooltipString,

    bool& retry,

    AcGiViewportDraw* pDrawContext,

    AcApDocument* document,

    bool pointComputed,

    int history,

    const AcGePoint3d& lastPoint,

    const AcGePoint3d& rawPoint,

    const AcGePoint3d& grippedPoint,

    const AcGePoint3d& cartesianSnappedPoint,

    const AcGePoint3d& osnappedPoint,

    // const AcArray& customOsnapModes

    const AcArray& pickedEntities,

    const AcArray< AcDbObjectIdArray,

    AcArrayObjectCopyReallocator< AcDbObjectIdArray > >&

    nestedPickedEntities,

    // Of 0th element in pickedEntities.

    int gsSelectionMark,

    // AutoSnap Info:

    const AcArray& keyPointEntities,

    const AcArray& alignmentPaths,

    const AcGePoint3d& computedPoint,

    const char* tooltipString)

    {

    // Change the computed point to an offset of (0.2, 0.2, 0.2)

    // if the current computed point is an object snap point.

    //

    if (pointComputed && history & Acad::eOsnapped)

    {

    changedPoint = true;

    newPoint = osnappedPoint + AcGeVector3d(0.2,0.2,0.0);

    pDrawContext->geometry().circle(newPoint, 0.1,

    AcGeVector3d::kZAxis);

    }

    return Acad::eOk;

    }

    // Input point monitor

    IPM my_ipm;

    // Input point filter

    IPF my_ipf;

    // Installs an input point monitor.

    //

    void testipm()

    {

    curDoc()->inputPointManager()->addPointMonitor(&my_ipm);

    }

    // Installs an input point filter.

    //

    void testipf()

    {

    curDoc()->inputPointManager()->registerPointFilter(&my_ipf);

    }

    // Turns on forced entity picking.

    //

    void testfp()

    {

    curDoc()->inputPointManager()->turnOnForcedPick();

    }

    // Disables the system cursor graphics.

    //

    void testcursor()

    {

    curDoc()->inputPointManager()->disableSystemCursorGraphics();

    }

    extern "C" __declspec(dllexport)

    AcRx::AppRetCode

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

    {

    switch (msg)

    {

    case AcRx::kInitAppMsg:

    acrxRegisterAppMDIAware(p);

    acrxUnlockApplication(p);

    acedRegCmds->addCommand("mkr", "testipm", "ipm",

    ACRX_CMD_TRANSPARENT, testipm);

    acedRegCmds->addCommand("mkr", "testipf", "ipf",

    ACRX_CMD_TRANSPARENT, testipf);

    acedRegCmds->addCommand("mkr", "testfp", "fp",

    ACRX_CMD_TRANSPARENT, testfp);

    acedRegCmds->addCommand("mkr", "testcursor", "cursor",

    ACRX_CMD_TRANSPARENT, testcursor);

    break;

    case AcRx::kUnloadAppMsg:

    acedRegCmds->removeGroup("mkr");

    break;

    }

    return AcRx::kRetOK;

    }

    Фильтрация для Расширенных Данных

    Расширенные данные (xdata) - текстовые строки, числовые значения, трехмерные точки, расстояния, названия уровня, или другие данные, приложенные к объекту, типично внешним приложением.
    Размер расширенных данных - байты 16КБ.
    Вы можете отыскивать расширенные данные для специфического приложения,  определяя его имя в списке фильтра, используя -3 код группы. AcedSSGet () функциональные примитивы возвращений с расширенными данными, зарегистрированными к указанному имени; acedSSGet () не отыскивает индивидуума, расширил элементы данных (с кодами группы в диапазоне 1000-2000).
    Следующий типовой кодовый фрагмент выбирает все круги, которые расширили данные, зарегистрированные на приложение, чей ИДЕНТИФИКАТОР - “APPNAME”.
    eb1.restype = 0; // Entity type
    strcpy(sbuf1, "CIRCLE");
    eb1.resval.rstring = sbuf1; // Circle
    eb1.rbnext = &eb2;
    eb2.restype = -3; // Extended data
    eb2.rbnext = &eb3;
    eb3.restype = 1001;
    strcpy(sbuf2, "APPNAME");
    eb3.resval.rstring = sbuf2; // APPNAME application
    eb3.rbnext = NULL;
    // Select circles with XDATA registered to APPNAME.
    acedSSGet("X", NULL, NULL, &eb1, ssname1);
    Если больше чем одно прикладное имя включены в список, acedSSGet () включает примитив в выбор, устанавливают только, если это расширило{*продлило*} данные для всех указанных приложений. Например, следующий код выбирает круги расширенными{*продленными*} данными, зарегистрированными к “APP1” и “APP2”.
    eb1.restype = 0; // Entity type
    strcpy(sbuf1, "CIRCLE");
    eb1.resval.rstring = sbuf1; // Circle
    eb1.rbnext = &eb2;
    eb2.restype = -3; // Extended data
    eb2.rbnext = &eb3;
    eb3.restype = 1001;
    strcpy(sbuf2, "APP1");
    eb2.resval.rstring = sbuf2; // APP1 application
    eb2.rbnext = &eb4;
    eb4.restype = 1001; // Extended data
    strcpy(sbuf3, "APP2");
    eb4.resval.rstring = sbuf3; // APP2 application
    eb4.rbnext = NULL;
    // Select circles with XDATA registered to APP1 & APP2.

    acedSSGet("X", NULL, NULL, &eb1, ssname1);

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

    eb1.restype = 0; // Entity type

    strcpy(sbuf1, "CIRCLE");

    eb1.resval.rstring = sbuf1; // Circle

    eb1.rbnext = &eb2;

    eb2.restype = -3; // Extended data

    eb2.rbnext = &eb3;

    eb3.restype = 1001; // Extended data

    strcpy(sbuf2, "APP1,APP2");

    eb3.resval.rstring = sbuf2; // Application names

    eb3.rbnext = NULL;

    // Select circles with XDATA registered to APP1 or APP2.

    acedSSGet("X", NULL, NULL, &eb1, ssname1);

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

    strcpy(sbuf2, "APP[12]");

    Фильтрация Точки ввода

    Фильтры Точки ввода вызваны для всей строки и событий цифрового преобразователя, когда точка приобретается. Они могут изменять конечную позицию точки, возвращенную вызывающей программе в соответствии с AutoCAD и ToolTip
    строкой, отображенной в соответствии с AutoCAD.
    Фильтры Точки ввода обработаны перед любыми мониторами точки ввода, но в конце концов другие вычисления точки ввода выполнены в соответствии с AutoCAD. Точки вывода все еще подчиненны к AutoCAD XYZ
    фильтрация точки.
    ОБРАТИТЕ ВНИМАНИЕ Только на один фильтр точки ввода, может быть активен одновременно.

    Формирование и Регистрация COM DLL

    Файл системного реестра, который описывает ваше приложение, библиотеку типов, и объекты Automation, должен быть объединен в системный реестр системы Windows прежде, чем компоненты в вашем DLL будут доступны. Некоторые дополнительные шаги требованы, чтобы связать успешно COM DLL и отдельное ObjectARX-приложение.
    Готовить COM DLL, который является отдельным от ObjectARX-приложения
    1 Формируют COM DLL.
    2 Добавляют любые украшенные названия символа, которые появляются по ошибкам компоновщика как нерешенные внешние символы к секции Экспорта ObjectARX файла DEF.
    3 Восстанавливают ObjectARX-приложение.
    4 В COM DLL, выберите Назначения из меню Project.
    5 На позиции табуляции Link, добавьте библиотеку для вашего ObjectARX-приложения.
    6 Выбирают OK.
    7 Продолжают шаги ниже, чтобы формировать и регистрировать ваш COM DLL.

    Формирование Иерархии Монопольных использований

    Следующий пример иллюстрирует, как формировать иерархию монопольных использований, используя функции ObjectARX. Пример показывает заголовку и исходным файлам для нового класса, OwnerDemo, который иллюстрирует, как создать дерево монопольных использований. Этот класс имеет два компонента данных, простое целое число, чтобы представить нормальные данные, и жесткое монопольное использование компонент данных ИДЕНТИФИКАТОРА, чтобы провести{*держать*} объект ID находящегося в собственности объекта. Функции
    Обеспечиваются для получения и установки значений обоих компонентов данных.
    Пример также отменяет четыре требуемых виртуальных функции:
    dwgInFields(), dwgOutFields(), dxfInFields(), и  dxfOutFields().
    Иерархия монопольных использований установлена в createObjs () подпрограмма к концу примера. Объект имеет объект B. Объект B имеет объект C. Объект добавлен к словарю (ASDK_DICT) в названном объектном словаре. printOut() и listTree () подпрограммы печатает информацию относительно объектов в ASDK_DICT словаре.
    ObjectARX Example
    // Class declarations
    //
    class AsdkOwnerDemo : public AcDbObject
    // This is a custom object class to demonstrate what is
    // necessary to create ownership trees.
    //
    // To keep it simple, this class has two data members: a
    // simple integer to represent normal data, and a hard
    // ownership ID data member to hold the object ID of an owned
    // object.
    //
    // Get and set functions are provided for both data members.
    //
    {
    public:
    ACRX_DECLARE_MEMBERS(AsdkOwnerDemo);
    AsdkOwnerDemo(): mIntval(0) {};
    AsdkOwnerDemo(const Adesk::Int16& val): mIntval(val) {};
    Adesk::Int16 intData();
    Acad::ErrorStatus setIntData(const Adesk::Int16&);
    AcDbHardOwnershipId idData();
    Acad::ErrorStatus setIdData(const AcDbHardOwnershipId&);
    Acad::ErrorStatus dwgInFields (AcDbDwgFiler*);
    Acad::ErrorStatus dwgOutFields(AcDbDwgFiler*) const;
    Acad::ErrorStatus dxfInFields (AcDbDxfFiler*);
    Acad::ErrorStatus dxfOutFields(AcDbDxfFiler*) const;

    private:

    Adesk::Int16 mIntval;

    AcDbHardOwnershipId mObjId;

    };

    ACRX_DXF_DEFINE_MEMBERS(AsdkOwnerDemo, AcDbObject,

    AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent, 0,

    ASDKOWNERDEMO, OWNERSHIP);

    // Gets the value of the integer data member.

    //

    Adesk::Int16

    AsdkOwnerDemo::intData()

    {

    assertReadEnabled();

    return mIntval;

    }

    // Sets the value of the integer data member.

    //

    Acad::ErrorStatus

    AsdkOwnerDemo::setIntData(const Adesk::Int16& val)

    {

    assertWriteEnabled();

    mIntval = val;

    return Acad::eOk;

    }

    // Returns a copy of the ownership ID data member.

    //

    AcDbHardOwnershipId

    AsdkOwnerDemo::idData()

    {

    assertReadEnabled();

    return mObjId;

    }

    // Sets the value of the ownership ID data member.

    //

    Acad::ErrorStatus

    AsdkOwnerDemo::setIdData(const AcDbHardOwnershipId& ownedId)

    {

    if (ownedId.asOldId() == 0L) {

    return Acad::eInvalidInput;

    }

    assertWriteEnabled();

    mObjId = ownedId;

    // Now set the backpointer. A transaction is used for

    // opening the object, so if the object is already

    // open it won’t prevent this setting from taking place.

    //

    AcDbObject *pObj;

    AcTransaction *pTrans

    = actrTransactionManager->startTransaction();

    pTrans->getObject(pObj, ownedId, AcDb::kForWrite);

    pObj->setOwnerId(objectId());

    actrTransactionManager->endTransaction();

    return Acad::eOk;

    }

    // Files data in from a DWG file.

    //

    Acad::ErrorStatus

    AsdkOwnerDemo::dwgInFields(AcDbDwgFiler* filer)

    {

    assertWriteEnabled();

    AcDbObject::dwgInFields(filer);

    // For wblock filing we wrote out our owner as a hard

    // pointer Id so now we need to read it in to keep things

    // in sync.

    //

    if (filer->filerType() == AcDb::kWblockCloneFiler) {

    AcDbHardPointerId id;

    filer->readItem(&id);

    }

    filer->readItem(&mIntval);

    filer->readItem(&mObjId);

    return filer->filerStatus();

    }

    // Files data out to a DWG file.

    //

    Acad::ErrorStatus

    AsdkOwnerDemo::dwgOutFields(AcDbDwgFiler* filer) const

    {

    assertReadEnabled();

    AcDbObject::dwgOutFields(filer);


    // Since objects of this class will be in the Named

    // Objects Dictionary tree and may be hard referenced

    // by some other object, to support wblock we need to

    // file out our owner as a hard pointer Id so that it

    // will be added to the list of objects to be wblocked

    //

    if (filer->filerType() == AcDb::kWblockCloneFiler)

    filer->writeHardPointerId((AcDbHardPointerId)ownerId());

    filer->writeItem(mIntval);

    filer->writeItem(mObjId);

    return filer->filerStatus();

    }

    // Files data in from a DXF file.

    //

    Acad::ErrorStatus

    AsdkOwnerDemo::dxfInFields(AcDbDxfFiler* filer)

    {

    assertWriteEnabled();

    Acad::ErrorStatus es;

    if ((es = AcDbObject::dxfInFields(filer)) != Acad::eOk)

    {

    return es;

    }

    // Check if we’re at the right subclass data marker.

    //

    if (!filer->atSubclassData("AsdkOwnerDemo")) {

    return Acad::eBadDxfSequence;

    }

    struct resbuf inbuf;

    while (es == Acad::eOk) {

    if ((es = filer->readItem(&inbuf)) == Acad::eOk) {

    if (inbuf.restype == AcDb::kDxfInt16) {

    mIntval = inbuf.resval.rint;

    } else if (inbuf.restype == AcDb::kDxfHardOwnershipId)

    {

    acdbGetObjectId(mObjId,

    inbuf.resval.rlname);

    }

    }

    }

    return filer->filerStatus();

    }

    // Files data out to a DXF file.

    //

    Acad::ErrorStatus

    AsdkOwnerDemo::dxfOutFields(AcDbDxfFiler* filer) const

    {

    assertReadEnabled();

    AcDbObject::dxfOutFields(filer);

    filer->writeItem(AcDb::kDxfSubclass, "AsdkOwnerDemo");

    filer->writeItem(AcDb::kDxfInt16, mIntval);

    // Null object IDs are invalid: don’t write them out.

    //

    if (mObjId.asOldId() != 0L) {

    filer->writeItem(AcDb::kDxfHardOwnershipId, mObjId);

    }

    return filer->filerStatus();

    }

    // Creates an AsdkOwnerDemo object (pObjC) and adds data to

    // it. Then, AsdkOwnerDemo pObjC is created and set to be

    // the owner of pObjC. Next, AsdkOwnerDemo pObjA is created

    // and set to own pObjB. Finally, pObjA is added to a

    // dictionary in the named object dictionary. Technically,

    // we could just add pObjA to the named object dictionary


    // itself, but that’ s not appropriate because it would clutter

    // up the named object dictionary.

    //

    void

    createObjs()

    {

    AcDbObjectId objIdA, objIdB, objIdC;

    AcDbDictionary *pNamedobj;

    AcDbDictionary *pDict = NULL;

    AcDbDatabase *pCurDwg = acdbHostApplicationServices()->workingDatabase();

    // Create object C with a dummy integer data value of 3.

    //

    AsdkOwnerDemo *pObjC = new AsdkOwnerDemo(3);

    // Append object C to database without setting an owner.

    //

    pCurDwg->addAcDbObject(objIdC, pObjC);

    pObjC->close();

    // Create object B with a dummy integer data value of 2.

    //

    AsdkOwnerDemo *pObjB = new AsdkOwnerDemo(2);

    // Append object B to the database without setting an owner.

    //

    pCurDwg->addAcDbObject(objIdB, pObjB);

    // Now set up ownership for object C. The

    // AsdkOwnerDemo::setIdData() function takes the

    // objectId parameter and copies it into the

    // AcDbHardOwnershipId data member. This places the

    // object ID in a position to be filed out/in via the

    // dwgInFields/dwgOutFields/dxfInFields/dxfOutFields

    // member functions. This constitutes primary

    // "ownership." The AsdkOwnerDemo::setIdData() function

    // also calls each owned object’s setOwnerId() member

    // function to set the backpointer and establish the

    // full two-way ownership link.

    //

    pObjB->setIdData(objIdC);

    pObjB->close();

    // Create object A with a dummy integer data value of 1.

    //

    AsdkOwnerDemo *pObjA = new AsdkOwnerDemo(1);

    // Next, add objA to a dictionary in the named object

    // dictionary. This will establish ownership for objA,

    // set the ownership backlink, and add it to the

    // database.

    //

    pCurDwg->getNamedObjectsDictionary(pNamedobj, AcDb::kForWrite);

    // Get a pointer to the ASDK_DICT dictionary. If it

    // doesn’t exist, then create it and add it to the

    // named object dictionary.

    //

    if (pNamedobj->getAt("ASDK_DICT", (AcDbObject*&) pDict,

    AcDb::kForWrite) == Acad::eKeyNotFound)

    {

    pDict = new AcDbDictionary;


    AcDbObjectId DictId;

    pNamedobj->setAt("ASDK_DICT", pDict, DictId);

    }

    pNamedobj->close();

    // Add object A to the ASDK_DICT dictionary.

    //

    pDict->setAt("OBJA", pObjA, objIdA);

    pDict->close();

    // Now set up ownership for object B.

    //

    pObjA->setIdData(objIdB);

    pObjA->close();

    }

    // The list tree function runs through all objects in the

    // ASDK_DICT dictionary, follows their ownership trees, and

    // lists out information on all objects in the tree.

    //

    void

    listTree()

    {

    AcDbDictionary *pNamedobj;

    AcDbDictionary *pDict;

    acdbHostApplicationServices()->workingDatabase()

    ->getNamedObjectsDictionary(pNamedobj, AcDb::kForWrite);

    // Get a pointer to the ASDK_DICT dictionary.

    //

    pNamedobj->getAt("ASDK_DICT",(AcDbObject*&)pDict,

    AcDb::kForRead);

    pNamedobj->close();

    // Run through the entries and list their backpointers.

    //

    AcDbDictionaryIterator *pDictItr = pDict->newIterator();

    for (; !pDictItr->done(); pDictItr->next()) {

    printOut(pDictItr->objectId());

    }

    pDict->close();

    }

    // Recursively walks down an ownership tree of AsdkOwnerDemo

    // class objects, printing out information on each one.

    //

    void

    printOut(AcDbObjectId id)

    {

    AsdkOwnerDemo *pDemo;

    acdbOpenObject((AcDbObject*&)pDemo, id, AcDb::kForRead);

    acutPrintf("\nIntdata: %d ObjId: %ld Backpointer:"

    " %ld OwnedObj: %ld", pDemo->intData(),

    (pDemo->objectId()).asOldId(),

    (pDemo->ownerId()).asOldId(),

    (pDemo->idData()).asOldId());

    // Recursive tree walk

    //

    if ((pDemo->idData()).asOldId() != 0L) {

    printOut(pDemo->idData());

    }

    pDemo->close();

    }

    // The initialization function is called from acrxEntryPoint()

    // during kInitAppMsg case. This function is used to add commands

    // to the command stack and to add classes to the ACRX class

    // hierarchy.

    //

    void

    initApp()

    {

    acedRegCmds->addCommand("ASDK_OWNERSHIP_COMMANDS",

    "ASDK_CREATE", "CREATE",ACRX_CMD_MODAL, createObjs);


    acedRegCmds->addCommand("ASDK_OWNERSHIP_COMMANDS",

    "ASDK_LISTREE", "LISTREE",ACRX_CMD_MODAL, listTree);

    AsdkOwnerDemo::rxInit();

    acrxBuildClassHierarchy();

    }

    // The clean up function is called from acrxEntryPoint() during the

    // kUnloadAppMsg case. This function removes this application’s

    // command set from the command stack and the

    // AsdkOwnerDemo class from the ARX runtime class tree.

    //

    void

    unloadApp()

    {

    acedRegCmds->removeGroup("ASDK_OWNERSHIP_COMMANDS");

    // Remove the AsdkOwnerDemo class from the ACRX runtime

    // class hierarchy. If this is done while the database is

    // still active, it should cause all objects of class

    // AsdkOwnerDemo to be turned into proxies.

    //

    deleteAcRxClass(AsdkOwnerDemo::desc());

    }

    // ObjectARX entry point

    //

    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();

    }

    return AcRx::kRetOK;

    }

    Формирование Комплексных Приложений

    ObjectARX поддерживает развитие комплексных приложений, обеспечивая следующие возможности:
    ·
    уведомление
    · управление Транзакции
    · Глубоко имитирующий
    · редактирование Ссылки(справочников)
    · расширение Протокола
    · поддержка Proxy-объекта
    · Взаимодействие с другими средами
    ObjectARX приложения может связываться с другими интерфейсами программирования, типа VLisp, ActiveX, и COM. Кроме того, ObjectARX приложения могут взаимодействовать с Internet связанными с объектами URL,  загружая и сохраняя чертежные файлы от WWW.

    Формирование Приложения

    Приложение, которое использует AcBr библиотеку, должно иметь библиотечный файл, libacbr.dll доступный, чтобы связаться против. Более важно, библиотека необходима, чтобы гарантировать надлежащую регистрацию классов AcBr с ObjectARX во время выполнения. Поэтому важно, что libacbr.dll, быть явно загружено приложением, если это уже не было загружено разработчиком модели или другим приложением.  Лучший способ гарантировать это состоял в том, чтобы использовать acrxDynamicLoader () и acrxClassDictionary () чтобы загрузить libacbr.dll и проверять, было ли это загружено.
    Следующий кодовый фрагмент обеспечивает пример:
    AcRx::AppRetCode
    acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt)
    {
    switch (msg) {
    case AcRx::kInitAppMsg:
    if (!acrxClassDictionary->at("AcBrEntity")) {
    acrxDynamicLinker->loadModule("libacbr.dll", 1);
    acutPrintf("\n libacbr loaded \n");
    }
    acedRegCmds->addCommand(
    "MY_APP",
    "MY_CMD",
    "MY_CMD",
    ACRX_CMD_MODAL,
    &myCmdImp);
    acrxUnlockApplication(pkt); // try to allow unloading
    break;
    case AcRx::kUnloadAppMsg:
    acedRegCmds->removeGroup("MY_APP");
    break;
    default:
    break;
    }
    return AcRx::kRetOK;
    }
    ПРИМЕЧАНИЕ, которое важно не разгрузить libacbr.dll на выход от приложения, как другие приложения (или разработчик модели) может все еще зависеть от его присутствия.

    Формировать и регистрировать ваш составляющий сервер

    1 Формируют приложение COM.
    Сообщение может казаться, указывая, что REGSRVR32 не сумел загружать AutoCAD.
    Чтобы устранять это сообщение в будущем, удалите все заказные шаги компоновки для регистрации сервера COM от ваших назначений проекта COM.
    2 Создают файл REG для вашего приложения с GUIDS для объекта и библиотеки типов, которые соответствуют в файле IDL.
    Файл REG должен регистрировать следующую информацию:
    §
    имя объекта AcRxClass (так, чтобы GetIUnknownOfObject мог располагать класс)
    § библиотека типов объекта (так, чтобы, когда ATL вызывает LoadRegTypeLib, это будет преуспевать)
    § прикладное имя как сервер для объекта COM с той частностью CLSID (так, чтобы CoCreateInstance () работал правильно)
    Следующий пример - файл REG для AsdkSquareWrapper:
     REGEDIT
    ; This .REG file may be used by your SETUP program.
    ; If a SETUP program is not available, the entries below will be
    ; registered in your InitInstance automatically with a call to
    ; CWinApp::RegisterShellFileTypes and
    ; COleObjectFactory::UpdateRegistryAll.
    HKEY_CLASSES_ROOT\TypeLib\{800F70A1-6DE9-11D2-A7A6-0060B0872457}
    HKEY_CLASSES_ROOT\TypeLib\{800F70A1-6DE9-11D2-A7A6-0060B0872457}
    \1.1 = AsdkSquareLib 1.0 Type Library
    HKEY_CLASSES_ROOT\TypeLib\{800F70A1-6DE9-11D2-A7A6-0060B0872457}
    \1.1\0\win32=
    E:\TEMP\square\AsdkSquareLib\Debug\AsdkSquareLib.dll
    HKEY_CLASSES_ROOT\TypeLib\{800F70A1-6DE9-11D2-A7A6-0060B0872457}
    \1.1\9\win32 =
    E:\TEMP\square\AsdkSquareLib\Debug\AsdkSquareLib.dll
    HKEY_CLASSES_ROOT\CLSID\{800F70AE-6DE9-11D2-A7A6-0060B0872457} =
    AsdkSquareWrapper Class
    HKEY_CLASSES_ROOT\CLSID\{800F70AE-6DE9-11D2-A7A6-0060B0872457}
    \InProcServer32 =
    E:\TEMP\square\AsdkSquareLib\Debug\AsdkSquareLib.dll
    HKEY_CLASSES_ROOT\Interface\{800F70AD-6DE9-11D2-A7A6-0060B0872457}
    = IAsdkSquareWrapper Interface
    HKEY_CLASSES_ROOT\Interface\{800F70AD-6DE9-11D2-A7A6-0060B0872457}
    \TypeLib = {E3D2C633-69C9-11D2-A7A2-0060B0872457}
    HKEY_CLASSES_ROOT\Interface\{800F70AD-6DE9-11D2-A7A6-0060B0872457}
    \ProxyStubClsid32 = {00020424-0000-0000-C000-000000000046}
    3 Выполненный файл РЕДЖА от Проводника.

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

    Некоторые функции работают на данных примитива и могут использоваться, чтобы изменить базу данных текущего рисунка. AcdbEntDel () функция удаляет указанный примитив. Примитив не очищен от базы данных, пока Вы не оставляете текущий рисунок.
    Так, если приложение вызывает acdbEntDel () второй раз в течение того сеанса и определяет тот же самый примитив, примитив восстановлен. (Вы можете использовать acdbHandEnt () чтобы восстановить{*отыскать*} названия{*имена*} удаленных примитивов.)
    ОБРАТИТЕ ВНИМАНИЕ На использование acdbEntDel (), атрибуты, и вершина ломаной линии не может быть удалена независимо от их родительских примитивов; acdbEntDel () работает только на основных примитивах. Чтобы удалять атрибут или вершину, используйте acedCommand () или acedCmd () чтобы вызвать AutoCAD ATTEDIT или команды PEDIT, используйте acdbEntMod () чтобы переопределить примитив без нежелательных подпримитивов, или откройте вершину, или припишите, и используйте ее стирание () метод стереть это.
    AcdbEntGet () функция возвращает данные определения указанного примитива.
    Данные возвращены как список связей буферов результатов. Тип каждого элемента (буфер) в списке определен кодом группы DXF. Первый элемент в списке содержит текущее имя примитива (restype == -1).
    ObjectARX-приложение могло отыскивать и печатать данные определения для примитива,  используя следующий две функции. (Printdxf () функция не обрабатывает расширенные данные.)
    void getlast()
    {
    struct resbuf *ebuf, *eb;
    ads_name ent1;
    acdbEntLast(ent1);
    ebuf = acdbEntGet(ent1);
    eb = ebuf;
    acutPrintf("\nResults of entgetting last entity\n");
    // Print items in the list.
    for (eb = ebuf; eb != NULL; eb = eb->rbnext)
    printdxf(eb);
    // Release the acdbEntGet() list.
    acutRelRb(ebuf);
    }
    int printdxf(eb)
    struct resbuf *eb;
    {
    int rt;
    if (eb == NULL)
    return RTNONE;
    if ((eb->restype >= 0) && (eb->restype <= 9))
    rt = RTSTR ;
    else if ((eb->restype >= 10) && (eb->restype <= 19))

    rt = RT3DPOINT;

    else if ((eb->restype >= 38) && (eb->restype <= 59))

    rt = RTREAL ;

    else if ((eb->restype >= 60) && (eb->restype <= 79))

    rt = RTSHORT ;

    else if ((eb->restype >= 210) && (eb->restype <= 239))

    rt = RT3DPOINT ;

    else if (eb->restype < 0)

    // Entity name (or other sentinel)

    rt = eb->restype;

    else

    rt = RTNONE;

    switch (rt) {

    case RTSHORT:

    acutPrintf("(%d . %d)\n", eb->restype,

    eb->resval.rint);

    break;

    case RTREAL:

    acutPrintf("(%d . %0.3f)\n", eb->restype,

    eb->resval.rreal);

    break;

    case RTSTR:

    acutPrintf("(%d . \"%s\")\n", eb->restype,

    eb->resval.rstring);

    break;

    case RT3DPOINT:

    acutPrintf("(%d . %0.3f %0.3f %0.3f)\n",

    eb->restype,

    eb->resval.rpoint[X], eb->resval.rpoint[Y],

    eb->resval.rpoint[Z]);

    break;

    case RTNONE:

    acutPrintf("(%d . Unknown type)\n", eb->restype);

    break;

    case -1:

    case -2:

    // First block entity

    acutPrintf("(%d . )\n", eb->restype, eb->resval.rlname[0]);

    }

    return eb->restype;

    }

    В следующем примере, следующие (заданные по умолчанию) условия{*состояния*} обращаются к текущему рисунку.

    § текущий уровень - 0

    § linetype - НЕПРЕРЫВЕН

    § текущее повышение - 0

    § маркеры примитива заблокированы

    Также, пользователь рисовал линию со следующей последовательностью команд:

    Command: line

    From point: 1,2

    To point: 6,6

    To point: ENTER

    Тогда запрос к getlast () печатал бы следующий (значение имени изменится).

    Результат выполнения acdbEntGet () для последнего примитива:

    (-1 . )

    (0 . "LINE")

    (8 . "0")

    (10 1.0 2.0 0.0)

    (11 6.0 6.0 0.0)

    (210 0.0 0.0 1.0)


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

    Буфер результатов в начале списка (с -1 кодом стража) содержит имя примитива, который этот список представляет. AcdbEntMod () функциональные использования это, чтобы идентифицировать примитив, который нужно изменить.

    Коды для компонентов примитива (сохраненный в restype поле) - используемые DXF. Как с DXF, элементы заголовка примитива возвращены только, если они имеют значения другие чем значение по умолчанию. В отличие от DXF, необязательные поля определения примитива возвращены независимо от того, равняются ли они их значениям по умолчанию. Это упрощает обработку; приложение может всегда предполагать, что эти поля присутствуют. Также в отличие от DXF, связанного X, Y, и координат Z возвращены как одиночная переменная точки (resval.rpoint), не как отдельный X (10), Y (20), и Z (30) групп. Значение restype содержит номер группы координаты X (в диапазоне 10-19).

    Чтобы находить группу с определенным кодом, приложение может пересекать список. Entitem () функция, показанная здесь ищет список буфера результата группу указанного типа.

    static struct resbuf *entitem(rchain, gcode)

    struct resbuf *rchain;

    int gcode;

    {

    while ((rchain != NULL) && (rchain->restype != gcode))

    rchain = rchain->rbnext;

    return rchain;

    }

    Если код группы DXF, указанный gcode параметром - не подарок{*настоящее*} в списке (или если gcode - не,  правильная{*допустимая*} группа DXF), entitem () “ уменьшается конец ” и возвращает NULL. Обратите внимание, что entitem () эквивалентен функции AutoLISP (assoc).

    AcdbEntMod () функция изменяет примитив. Это передает список, который имеет тот же самый формат как список, возвращенный acdbEntGet (), но с некоторыми из значений группы примитива (возможно) изменяемых приложением. Эти функциональные дополнения acdbEntGet (); первичные средства,  которыми ObjectARX-приложение модифицирует базу данных - восстанавливая{*отыскивая*} примитив с acdbEntGet (), изменяя его список примитива, и затем пропуская список назад к базе данных с acdbEntMod ().


    ОБРАТИТЕ ВНИМАНИЕ, чтобы восстановить значение по умолчанию цвета примитива или linetype, использовать acdbEntMod () чтобы установить цвет в 256, который является BYLAYER, или linetype к BYLAYER.

    Следующий кодовый фрагмент отыскивает данные определения первого примитива в рисунке, и изменяет его свойство уровня к MYLAYER.

    ads_name en;

    struct resbuf *ed, *cb;

    char *nl = "MYLAYER";

    if (acdbEntNext(NULL, en) != RTNORM)

    return BAD; // Error status

    ed = acdbEntGet(en); // Retrieve entity data.

    for (cb = ed; cb != NULL; cb = cb->rbnext)

    if (cb->restype == 8) { // DXF code for Layer

    // Check to make sure string buffer is long enough.

    if (strlen(cb->resval.rstring) < (strlen(nl)))

    // Allocate a new string buffer.

    cb->resval.rstring = realloc(cb->resval.rstring,

    strlen(nl) + 1);

    strcpy(cb->resval.rstring, nl);

    if (acdbEntMod(ed) != RTNORM) {

    acutRelRb(ed);

    return BAD; // Error

    }

    break; // From the for loop

    }

    acutRelRb(ed); // Release result buffer.

    Управление памятью - ответственность ObjectARX-приложения.

    Код в примере гарантирует, что строковый буфер - правильный размер, и это выпускает буфер результатов, возвращенный acdbEntGet () (и прошло к acdbEntMod ()) как только операция закончена, действительно ли запрос к acdbEntMod () преуспевает.

    ОБРАТИТЕ ВНИМАНИЕ, используете ли Вы acdbEntMod () чтобы изменить примитив на блочном определении, это воздействует на всю ВСТАВКУ или XREF к тому блоку; также, примитивы на блочных определениях не могут быть удалены acdbEntDel ().

    Приложение может также добавлять примитив к базе данных рисунка,  вызывая acdbEntMake () функция. Подобно acdbEntMod (), параметр к acdbEntMake () - список буфера результата, чей формат подобен таковому списка, возвращенного acdbEntGet (). (AcdbEntMake () запрос игнорирует поле имени примитива [-1], если это присутствует.) новый примитив добавлен в конец к базе данных рисунка (это становится последним{*прошлым*} примитивом в рисунке). Если примитив - сложный примитив (ломаная линия или блок), это не добавлено в конец к базе данных, пока это не закончено.


    Следующий типовой кодовый фрагмент создает круг на уровне MYLAYER.

    int status;

    struct resbuf *entlist;

    ads_point center = {5.0, 7.0, 0.0};

    char *layer = "MYLAYER";

    entlist = acutBuildList(RTDXF0, "CIRCLE",// Entity type

    8, layer, // Layer name

    10, center, // Center point

    40, 1.0, // Radius

    0 );

    if (entlist == NULL) {

    acdbFail("Unable to create result buffer list\n");

    return BAD;

    }

    status = acdbEntMake(entlist);

    acutRelRb(entlist); // Release acdbEntMake buffer.

    if (status == RTERROR) {

    acdbFail("Unable to make circle entity\n");

    return BAD;

    }

    И acdbEntMod () и acdbEntMake () исполняют,  те же самые проверки последовательности на данных примитива прошли к ним, поскольку команда DXFIN AutoCAD исполняет при чтении DXF файлы. Они терпят неудачу, если они не могут создавать правильные{*допустимые*} примитивы рисунка.

    Функции Имени Примитива

    Чтобы работать на примитиве, ObjectARX-приложение должно получить его имя для использования в последующем, вызывает{*звонит*} к функциям данных примитива или функциям набора выбора.
    Функции acedEntSel (), acedNEntSelP (), и acedNEntSel () возвращение не только имя примитива но и  дополнительная информация для использования приложения. Функции entsel требуют пользователей AutoCAD (или приложение) чтобы выбрать примитив,  определяя точку на графическом экране; все другие функции имени примитива могут восстановить{*отыскивать*} примитив, даже если это не видимо на экране или находится на закрепляемом уровне. Подобно acedGetxxx () функции, Вы можете иметь acedEntSel (), acedNEntSelP (), и acedNEntSel () возвращают ключевое слово вместо точки,  предшествуя им с запросом к acedInitGet ().
    Если запрос к acedEntSel (), acedNEntSelP (), или acedNEntSel () возвращает RTERROR, и Вы хотите знать, определил ли пользователь точку, которая не имела никакого примитива или нажал ли пользователь ВОЗВРАЩЕНИЕ, Вы можете осматривать значение ERRNO системной переменной. Если пользователь определил,  пустая точка, ERRNO равняется 7 (OL_ENTSELPICK). Если пользователь нажал ВОЗВРАЩЕНИЕ, ERRNO равняется 52 (OL_ENTSELNULL). (Вы можете использовать символические названия{*имена*}, если ваша программа включает файл заголовка.)
    ПРИМЕЧАНИЕ Вы должно осмотреть ERRNO немедленно после acedEntSel (), acedNEntSelP (), или acedNEntSel () возвращения. Последующий запрос ObjectARX может изменять{*заменять*} значение ERRNO.
    AcdbEntNext () функция восстанавливает{*отыскивает*} названия{*имена*} примитива последовательно. Если его первый параметр - NULL, это возвращает имя первого примитива в базе данных рисунка; если его первый параметр - имя примитива в текущем рисунке, это возвращает имя преуспевающего примитива.
    Следующий типовой кодовый фрагмент иллюстрирует, как acedSSAdd () может использоваться вместе с acdbEntNext () чтобы создать наборы выбора и добавлять членов к существующему набору.

    Ads_name ss, e1, e2;

    // Set e1 to the name of first entity.

    if (acdbEntNext(NULL, e1) != RTNORM) {

    acdbFail("No entities in drawing\n");

    return BAD;

    }

    // Set ss to a null selection set.

    acedSSAdd(NULL, NULL, ss);

    // Return the selection set ss with entity name e1 added.

    if (acedSSAdd(e1, ss, ss) != RTNORM) {

    acdbFail("Unable to add entity to selection set\n");

    return BAD;

    }

    // Get the entity following e1.

    if (acdbEntNext(e1, e2) != RTNORM) {

    acdbFail("Not enough entities in drawing\n");

    return BAD;

    }

    // Add e2 to selection set ss

    if (acedSSAdd(e2, ss, ss) != RTNORM) {

    acdbFail("Unable to add entity to selection set\n");

    return BAD;

    }

    Следующий типовой кодовый фрагмент использует acdbEntNext () чтобы “идти” через базу данных, один примитив одновременно.

    ads_name ent0, ent1;

    struct resbuf *entdata;

    if (acdbEntNext(NULL, ent0) != RTNORM) {

    acdbFail("Drawing is empty\n");

    return BAD;

    }

    do {

    // Get entity’s definition data.

    entdata = acdbEntGet(ent0);

    if (entdata == NULL) {

    acdbFail("Failed to get entity\n");

    return BAD;

    }

    .

    . // Process new entity.

    .

    if (acedUsrBrk() == TRUE) {

    acdbFail("User break\n");

    return BAD;

    }

    acutRelRb(entdata); // Release the list.

    ads_name_set(ent0, ent1); // Bump the name.

    } while (acdbEntNext(ent1, ent0) == RTNORM);

    ПРИМЕЧАНИЕ Вы можете также пройти базу данных,  “наталкиваясь” одиночная переменная в acdbEntNext () запрос (типа acdbEntNext (ent0, ent0)), но если Вы делаете, значение переменной,  больше не определено однажды цикл концы.

    AcdbEntLast () функция отыскивает имя последнего примитива в базе данных. Последний примитив - наиболее недавно созданный основной примитив, так что acdbEntLast () может быть вызван, чтобы получить имя примитива, который только что был создан посредством запроса к acedCommand (), acedCmd (), или acdbEntMake ().

    AcedEntSel () функция запрашивает пользователя AutoCAD выбирать примитив,  определяя точку на графическом экране; acedEntSel () возвращает, и имя примитива и значение указанной точки. Некоторые операции примитива требуют знания точки,  которой примитив был выбран. Примеры от набора существующих команд AutoCAD включают ПЕРЕРЫВ, ВЫРЕЗКУ, ПРОСТИРАЮТСЯ, и OSNAP.

    Функции Кривой

    Абстрактный класс AcDbCurve обеспечивает множество функций для действия на кривых, включая функции для проектирования, распространения{*продления*}, и кривых смещения, также как набора функций для запроса параметров кривой. Кривые могут быть определены или в пространстве{*пробеле*} параметра или в Декартовом координатном пространстве. Трехмерная кривая - функция одного параметра (f (t)), в то время как трехмерная поверхность - функция двух параметров (f (u, v)). Конверсионные функции позволяют Вам конвертировать{*преобразовывать*} данные от его представления параметра до точек в Декартовой системе координат.
    Сплайны, например, являются лучшими представленными в пространстве{*пробеле*} параметра. Чтобы разбивать сплайн на три равных части, Вы сначала находите параметры, которые соответствуют точкам сплайна и затем работают на сплайне в пространстве{*пробеле*} параметра.
    Кривые могут использоваться как границы вырезки, границы продления, и как объекты конструкции для создания сложных трехмерных примитивов.
    Вы можете проектировать кривую на план в данном направлении, как показано в следующем примере.
    // Accepts an ellipse object ID, opens the ellipse, and uses
    // its getOrthoProjectedCurve member function to create a
    // new ellipse that is the result of a projection onto the
    // plane with normal <1,1,1>. The resulting ellipse is
    // added to the model space block Table Record.
    //
    void
    projectEllipse(AcDbObjectId ellipseId)
    {
    AcDbEllipse *pEllipse;
    acdbOpenObject(pEllipse, ellipseId, AcDb::kForRead);
    // Now project the ellipse onto a plane with a
    // normal of <1, 1, 1>.
    //
    AcDbEllipse *pProjectedCurve;
    pEllipse->getOrthoProjectedCurve(AcGePlane(
    AcGePoint3d::kOrigin, AcGeVector3d(1, 1, 1)),
    (AcDbCurve*&)pProjectedCurve);
    pEllipse->close();
    AcDbObjectId newCurveId;
    addToModelSpace(newCurveId, pProjectedCurve);
    }
    // Accepts an ellipse object ID, opens the ellipse, and uses
    // its getOffsetCurves() member function to create a new
    // ellipse that is offset 0.5 drawing units from the
    // original ellipse.
    //
    void
    offsetEllipse(AcDbObjectId ellipseId)
    {
    AcDbEllipse *pEllipse;
    acdbOpenObject(pEllipse, ellipseId, AcDb::kForRead);
    // Now generate an ellipse offset by 0.5 drawing units.
    //
    AcDbVoidPtrArray curves;
    pEllipse->getOffsetCurves(0.5, curves);
    pEllipse->close();
    AcDbObjectId newCurveId;
    addToModelSpace(newCurveId, (AcDbEntity*)curves[0]);
    }

    Функции, не позволенные, в то время как диалоговое окно активно

    В то время как диалоговое окно активно, ads_start_dialog () функция выполняет ее команды. При этих условиях, Вы не можете называть некоторые функции ObjectARX, потому что ими или затрагивать дисплей, который не должен измениться, в то время как диалоговое окно видимо, или они требуют ввода пользователя, который не вовлекает диалоговое окно.
    Если приложение вызывает одну из этих функций прежде, чем это вызывает ads_done_dialog (), AutoCAD заканчивает все диалоговые окна и отображает сообщение ошибки слежения:
    AutoCAD rejected function
    AutoCAD CMDACTIVE переменная системы имеет немного, который указывает,является ли диалоговое окно активным. Для подробной информации относительно переменных системы, см. Ссылку Команды AutoCAD.
    Если пользователь ввел ввод, основанный на графическом экране скорее чем использование диалоговое окно непосредственно (например, определить точку или примитив), Вы должны скрыть диалоговое окно. То есть Вы должны вызвать ads_done_dialog () чтобы восстановить изображение графического экрана, и затем перезапускать диалоговое окно после того, как пользователь сделал выбор. Следующие списки показывают функции, которые не позволяются.

    Функции обратного вызова

    Определять, что действие принято когда диалоговое окно неперекрывающее расположение отобрано, связь функция ObjectARX с тем неперекрывающим расположением,  вызывая ads_action_tile (). В пределах повторного вызова, Вы часто нуждаетесь в доступе к атрибутам в файле DCL. Ads_get_tile () и ads_get_attr () функции обеспечивают, этот доступ (ads_get_attr () сохраняет значение в DCL, в то время как ads_get_tile () получает текущее значение во время выполнения), но значения Вы наиболее вероятно, чтобы использовать, связали с отобранным неперекрывающим расположением, обеспечиваются автоматически.
    В большинстве случаев, каждое активное неперекрывающее расположение в пределах диалогового окна генерирует повторный вызов. Функция повторного вызова должна делать законность, проверяющую ее связанное неперекрывающее расположение и модифицировать информацию в диалоговом окне, которое принадлежит значению неперекрывающего расположения.
    Модифицирование диалогового окна может включать издание сообщения об ошибках, отключение других неперекрывающих расположений, и отображения соответствующего текста в окне редактирования или списке.
    Только кнопка OK (или ее эквивалент) должна сделать запрос значений неперекрывающего расположения, чтобы сохранить назначения пользователь, наконец отобранный. Модифицируйте переменные, связанные со значениями неперекрывающего расположения в пределах повторного вызова для кнопки OK, не в пределах повторного вызова для индивидуального неперекрывающего расположения. Если постоянные переменные модифицированы в пределах индивидуальных повторных вызовов неперекрывающего расположения, не имеется никакого способа сбросить значения, если пользователь выбирает Отмену. Если повторный вызов кнопки OK обнаруживает ошибку, это должно отобразить сообщение об ошибках и фокус возвращения к неперекрывающему расположению по ошибке; это не должно выйти из диалогового окна.
    Когда диалоговое окно включает несколько неперекрывающих расположений, чей обработка подобна, может быть удобно связать эти неперекрывающие расположения с отдельной функцией повторного вызова. Принцип не совершения на изменения пользователя до пользователя определяет, OK все еще применяется. Функция повторного вызова, обычная к нескольким неперекрывающим расположениям может быть с формированием изображений при помощи таблицы, используя определяемые пользователем атрибуты, чтобы обеспечить значения определенными к каждому неперекрывающему расположению.

    Функции преобразования

    AcDbEntity класс обеспечивает две функции преобразования:
    virtual Acad::ErrorStatus
    AcDbEntity::transformBy(const AcGeMatrix3d& xform);
    virtual Acad::ErrorStatus
    AcDbEntity::getTransformedCopy(const AcGeMatrix3d& xform,
    AcDbEntity*& ent) const;
    TransformBy () функция изменяет примитив, используя указанную матрицу.
    В AutoCAD, это называется перемещением власти{*захвата*}, вращать, масштабировать, и отражать режимы. В некоторых случаях{*делах*}, однако, применяя преобразование требует, чтобы новый примитив был создан. В таких случаях{*делах*}, getTransformedCopy () функция используется так, чтобы заканчивающийся примитив мог быть образец различного класса чем первоначальный примитив.
    Когда Вы взрываете блочную ссылку{*справочники*}, которая неоднородно масштабировалась, getTransformedCopy () функция - обратился к примитивам в блочной ссылке{*справочниках*}, чтобы создать новые примитивы (см. “ Взрывающиеся Примитивы ” на странице 123).

    AcDbEntity класс предлагает две функции преобразования. TransformBy() функция применяет матрицу к объекту. GetTransformedCopy () функция дает возможность объекту возвратить копию себя С преобразованием, прикладным к этому.
    Если объект однородно масштабируется и ортогональный, заданное по умолчанию выполнение AcDbEntity:: getTransformedCopy () функция имитирует объект и затем вызывает transformBy () функция на имитируемом объекте. (Используйте AcGeMatrix3d:: isUniScaledOrtho () функция, чтобы определить, масштабируется ли входная матрица однородно и ортогональный.)
    Заказной AsdkPoly класс перегружает, и transformBy () функция и getTransformedCopy () функция. Когда AsdkPoly неравномерно масштабируется, это становится ломаной линией.
    Acad::ErrorStatus
    AsdkPoly::transformBy(const AcGeMatrix3d& xform)
    {
    // If we’re dragging, we aren’t really going to change our
    // data, so we don’t want to make an undo recording nor do
    // we really care if the object’s open for write.
    //
    if (mDragDataFlags & kCloneMeForDraggingCalled) {
    mDragDataFlags &= kUseDragCache;
    mDragPlaneNormal = mPlaneNormal;
    mDragElevation = mElevation;
    AcGeMatrix2d xform2d(xform.convertToLocal(mDragPlaneNormal,
    mDragElevation));
    mDragCenter = xform2d * center();
    mDragStartPoint = xform2d * startPoint();
    mDragPlaneNormal.normalize();
    } else {
    assertWriteEnabled();
    AcGeMatrix2d xform2d(xform.convertToLocal(mPlaneNormal,
    mElevation));
    mCenter.transformBy(xform2d);
    mStartPoint.transformBy(xform2d);
    mPlaneNormal.normalize();
    }
    return Acad::eOk;
    }
    Acad::ErrorStatus AsdkPoly::getTransformedCopy(
    const AcGeMatrix3d& mat,
    AcDbEntity*& ent) const
    {
    assertReadEnabled();
    Acad::ErrorStatus es = Acad::eOk;
    AcGePoint3dArray vertexArray;
    if ((es = getVertices3d(vertexArray)) != Acad::eOk)
    {
    return es;
    }
    for (int i = 0; i < vertexArray.length(); i++) {
    vertexArray[i].transformBy(mat);
    }
    AcDbSpline *pSpline = NULL;
    if ((es = rx_makeSpline(vertexArray, pSpline)) != Acad::eOk)
    {
    return es;
    }
    assert(pSpline != NULL);
    pSpline->setPropertiesFrom(this);
    ent = pSpline;
    return es;
    }

    Функции управления Дисплея

    Следующие функции управления дисплея не могут быть вызваны{*названы*}, в то время как диалоговое окно активно:
    § acedPrompt ()
    § acedMenuCmd ()
    § acedRedraw ()
    § acedGraphScr ()
    § acedTextScr ()
    § acedTextPage ()
    Функции, которые записывают текст, типа acutPrintf (), являются полезными для отображения информации при испытании диалогового окна, но они не должны использоваться в готовом изделии.

    Функции ввода пользователя

    Ввод пользователя или acedGetxxx () функции делают паузу для пользователя, чтобы ввести данные обозначенного типа, и возвращать значение в параметре результата. Приложение может определить необязательную подсказку, чтобы отобразить перед функциональными паузами.
    ОБРАТИТЕ ВНИМАНИЕ, что функции Several имеют подобные названия, но - не часть группы вводов пользователя: acedGetFunCode (), acedGetArgs (), acedGetVar (), и acedGetInput ().
    Следующие функции ведут себя подобно функциям ввода пользователя: acedEntSel (), acedNEntSelP (), acedNEntSel (), и acedDragGen (). Следующая таблица кратко описывает функции ввода пользователя.


    Имя функции
     Описание
    AcedGetInt
     Получает целочисленное значение
    AcedGetReal
     Получает реальное значение
    AcedGetDist
     Получает расстояние
    AcedGetAngle
     Получает угол (к 0 градусам как определено ANGBASE переменной)
    AcedGetOrient
     Получает угол (к 0 градусам вправо)
    AcedGetPoint
     Получает точку
    AcedGetCorner
     Получает угол прямоугольника
    AcedGetKword
     Получает ключевое слово (см. описание ключевых слов позже в этой секции)
    AcedGetString
     Получает строку

    С некоторыми функциями ввода пользователя типа acedGetString (), пользователь вводит значение в линию подсказки AutoCAD. С другими типа acedGetDist (), пользователь или вводит ответ на подсказке, выравнивают, или определяет значение,  выбирая точки на графическом экране.
    Если экран используется, чтобы определить значение, AutoCAD отображает линии с  резиновой полосой, которые являются подчиненными к прикладному контролю{*управлению*}. Предшествующий запрос к acedInitGet () может заставлять AutoCAD высвечивать линию резиновый полоса (или поле).
    AcedGetKword () функция отыскивает ключевое слово. Ключевые слова - также строковые значения, но они не содержат никакое незаполненное пространство, могут быть сокращены, и должны быть основаны перед acedGetKword () запрос запросом к acedInitGet (). Все функции ввода пользователя (кроме acedGetString ()) могут принимать значения ключевого слова в дополнение к значениям, которые они обычно возвращают, если acedInitGet () был вызван{*назван*}, чтобы основать ключевые слова. Функции Ввода пользователя, которые принимают ключевые слова, могут также принимать произвольный текст (без пространств{*пробелов*}).

    ПРИМЕЧАНИЕ Вы может также использовать acedInitGet () чтобы позволить acedEntSel (), acedNEntSelP (), и acedNEntSel () принять ввод ключевого слова. AcedDragGen () функция также признает ключевые слова.

    Пользователь AutoCAD не может ответить на функцию ввода пользователя,  вводя выражение AutoLISP.

    Функции ввода пользователя воспользуются преимуществом возможности с обнаружением ошибок AutoCAD. Тривиальные ошибки (типа ввода только единственный{*отдельный*} номер в ответ на acedGetPoint ()) пойман в соответствии с AutoCAD и не возвращен функцией ввода пользователя. Приложение должно только проверить условия{*состояния*}, показанные в следующей таблице.

    Возвращаемые значения для функций ввода пользователя

    Код

    Описание

    RTNORM

     Пользователь ввел имеющее силу значение

    RTERROR

     Функциональный запрос потерпел неудачу

    RTCAN

     Пользователь ввел ESC

    RTNONE

     Пользователь ввел только ВВОД

    RTREJ

     AutoCAD отклонил запрос как инвалид

    RTKWORD

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

    RTCAN случай позволяет пользователю отменить запрос приложения,  нажимая ESC. Это помогает приложению соответствовать стилю встроенного AutoCAD, командует, которые всегда позволяют отмену пользователя. Возвращаемые значения RTNONE и RTKWORD управляются функцией acedInitGet (): возвращения функции ввода пользователя RTNONE или RTKWORD только, если эти значения явно позволились предшествующим acedInitGet () запрос.

    Функция Инициализации Класса

    Функция инициализации класса для каждого класса - rxInit (). Приложение, которое определяет заказной класс, должно вызвать эту функцию во время выполнения инициализация.
    Эта функция определена автоматически каждым из три ACRX_xxx_DEFINE_MEMBERS () макрокоманды и исполняет следующие задачи:
    · Регистрирует заказной класс
    · Создает объект описателя класса
    · Размещает объект описателя класса в словарь класса
    Если Вы хотите определить ваш собственный rxInit () функция, используйте ACRX_DEFINE_MEMBERS () макрокоманда.

    Функция Утилиты Текстового поля

    Функция acedTextBox () находит диагональные координаты поля, которое включает текстовый примитив. Функция берет параметр, ent, который должен определить текстовое определение или строковую группу в форме списка буфера результата. AcedTextBox() функция устанавливает ее p1 параметр в минимальные КООРДИНАТНЫЕ координаты поля и ее p2 параметра к максимальным КООРДИНАТНЫМ координатам.
    Если текст горизонтален и не вращается, p1 (угол левой нижней части) и p2 (верхний правый угол) описывают поле ограничения текста. Координаты выражены в Системе координат Примитива (ECS) ent с началом координат (0,0) в левой оконечной точке опорной линии. (Начало координат - не угол левой нижней части, если текст содержит символы с подстрочными элементами, типа g и p.) Для примера, следующий рисунок показывает результатам применения acedTextBox () к текстовому примитиву с высотой 1.0. Рисунок также показывает опорной линии и началу координат текста.
    Функция Утилиты Текстового поля
    Следующий рисунок показывает значениям точки, которые acedTextBox () возвращается для выборок вертикального и выровненного текста. В обеих выборках, высота символов была введена как 1.0. (Для вращаемого текста, эта высота масштабируется, чтобы приспособить точки выравнивания.)
    Функция Утилиты Текстового поля
    Обратите внимание, что с вертикальными текстовыми стилями, точки все еще возвращаются в слева направо, заказ{*по приказу;порядок*} " основание к вершине ", так что первый список точки содержит отрицательные смещения от текстового начала координат.
    AcedTextBox () функция может также измерять строки в attdef и attrib примитивах. Для attdef, acedTextBox () измеряет строку отметки (группа 2); для attrib примитива, это измеряет текущее значение (группа 1).
    Следующая функция, которая использует некоторый примитив, обрабатывающий функции, запрашивает пользователя выбирать текстовый примитив, и затем тянет{*рисует*} поле ограничения вокруг текста от координат, возвращенных acedTextBox ().
    ОБРАТИТЕ ВНИМАНИЕ На выборку tbox () функциональные работы правильно только, если Вы - в настоящее время в Мировой системе координат (WCS). Если Вы - не, код должен преобразовать точки ECS, восстановленные{*отысканные*} из примитива в координаты UCS, используемые acedCommand (). См. “ Преобразования Системы координат ” на странице 271.

    int tbox()

    {

    ads_name tname;

    struct resbuf *textent, *tent;

    ads_point origin, lowleft, upright, p1, p2, p3, p4;

    ads_real rotatn;

    char rotatstr[15];

    if (acedEntSel("\nSelect text: ", tname, p1) != RTNORM) {

    acdbFail("No Text entity selected\n");

    return BAD;

    }

    textent = acdbEntGet(tname);

    if (textent == NULL) {

    acdbFail("Couldn’t retrieve Text entity\n");

    return BAD;

    }

    tent = entitem(textent, 10);

    origin[X] = tent->resval.rpoint[X]; //ECS coordinates

    origin[Y] = tent->resval.rpoint[Y];

    tent = entitem(textent, 50);

    rotatn = tent->resval.rreal;

    // acdbAngToS() converts from radians to degrees.

    if (acdbAngToS(rotatn, 0, 8, rotatstr) != RTNORM) {

    acdbFail("Couldn’t retrieve or convert angle\n");

    acutRelRb(textent);

    return BAD;

    }

    if (acedTextBox(textent, lowleft, upright) != RTNORM) {

    acdbFail("Couldn’t retrieve text box

    coordinates\n");

    acutRelRb(textent);

    return BAD;

    }

    acutRelRb(textent);

    // If not currently in the WCS, at this point add

    // acedTrans() calls to convert the coordinates

    // retrieved from acedTextBox().

    p1[X] = origin[X] + lowleft[X]; // UCS coordinates

    p1[Y] = origin[Y] + lowleft[Y];

    p2[X] = origin[X] + upright[X];

    p2[Y] = origin[Y] + lowleft[Y];

    p3[X] = origin[X] + upright[X];

    p3[Y] = origin[Y] + upright[Y];

    p4[X] = origin[X] + lowleft[X];

    p4[Y] = origin[Y] + upright[Y];

    if (acedCommand(RTSTR, "pline", RTPOINT, p1,

    RTPOINT, p2, RTPOINT, p3,RTPOINT, p4, RTSTR, "c",

    0) != RTNORM) {

    acdbFail("Problem creating polyline\n");

    return BAD;

    }

    if (acedCommand(RTSTR, "rotate", RTSTR, "L", RTSTR, "",

    RTPOINT, origin, RTSTR, rotatstr, 0) != RTNORM) {

    acdbFail("Problem rotating polyline\n");

    return BAD;

    }

    return GOOD;

    }

    Предшествующий пример использует команду ROTATE AutoCAD, чтобы вызвать вращение. Более прямой способ делать это состоит в том, чтобы включить вращение в вычисление точек поля, следующим образом:

    ads_real srot, crot;

    tent = entitem(textent, 50);

    rotatn = tent->resval.rreal;

    srot = sin(rotatn);

    crot = cos(rotatn);

    .

    .

    .

    p1[X] = origin[X] + (lowleft[X]*crot - lowleft[Y]*srot);

    p1[Y] = origin[Y] + (lowleft[X]*srot + lowleft[Y]*crot);

    p2[X] = origin[X] + (upright[X]*crot - lowleft[Y]*srot);

    p2[Y] = origin[Y] + (upright[X]*srot + lowleft[Y]*crot);

    p3[X] = origin[X] + (upright[X]*crot - upright[Y]*srot);

    p3[Y] = origin[Y] + (upright[X]*srot + upright[Y]*crot);

    p4[X] = origin[X] + (lowleft[X]*crot - upright[Y]*srot);

    p4[Y] = origin[Y] + (lowleft[X]*srot + upright[Y]*crot);

    Функциональная схема

    Диалоговые окна - для интерактивного использования. Сценарий может запустить диалоговое окно, но не может управлять это или обеспечивать ввод, как только это открыто. Это - тот же самый как acedCommand () и acedCmd () функции.
    Примеры, данные в этом разделе демонстрируют типичную последовательность функции диалогового окна следующим образом:
    1 Загружают файл DCL ads_load_dialog () запрос.
    2 Запрос ads_new_dialog () чтобы отобразить специфическое диалоговое окно на экране графики AutoCAD.
    Проверьте состояние значения, которое ads_new_dialog () возвращается. При запросе ads_start_dialog () когда ads_new_dialog () запрос потерпел неудачу, может иметь непредсказуемых результатов.
    3 Инициализируют диалоговое окно,  основывая значения неперекрывающего расположения, списки, и изображения.
    Функции, типично вызываемые в это время следующие:
    §
    ads_set_tile () и ads_mode_tile () для общего неперекрывающего расположения оценивает и состояния
    § ads_start_list (), ads_add_list (), и ads_end_list () для списков
    § ads_dimensions_tile () для установки значений неперекрывающего расположения, наряду с следующими функциями создания изображения:
    Ads_start_image ()
    Ads_vector_image ()
    Ads_fill_image ()
    Ads_slide_image ()
    Ads_end_image ()
    Вы можете также вызывать ads_client_data_tile () в это время, чтобы связать специфичные для приложения данные с диалоговым окном и его компонентами.
    Вызовите ads_action_tile () в этой точке, чтобы основать функции повторного вызова.
    4 Запрос ads_start_dialog () чтобы повернуть контроль над к диалоговому окну так, чтобы пользователь мог вводить ввод.
    5 ввода пользователя Процесса изнутри ваших функций. Это - то, когда Вы наиболее вероятно, чтобы использовать ads_get_tile (), ads_get_attr (), ads_get_attr_string (), ads_set_tile (), и ads_mode_tile ().
    6 пользователь нажимает кнопку выхода, вызывая функцию вызвать ads_done_dialog (), который тогда заставляет ads_start_dialog () возвращать значение. В этой точке, разгрузите файл DCL,  вызывая ads_unload_dialog ().

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

    Load_dialog

    New_dialog

    Action_tile; и другие инициализации

    Start_dialog

    ; Тогда изнутри выражений действия / функции повторного вызова:

    Get_tile; и другая входная обработка

    Set_tile

    Done_dialog

    Unload_dialog

    Эта схема обрабатывает только одно диалоговое окно и один файл DCL одновременно. Приложения обычно имеют множественные диалоговые окна. Самый простой и самый быстрый способ обрабатывать эти диалоговые окна состоит в том, чтобы сохранить все из них в единственном файле DCL. Запрос ads_load_dialog тогда загружает все диалоговые окна сразу, и Вы можете вызывать ads_new_dialog для любого диалогового окна. Если память ограничена, однако, Вам, вероятно, придется создавать множественные файлы DCL и использование ads_unload_dialog, чтобы удалить набор тех диалоговых окон от памяти прежде, чем Вы загружаете другой набор с ads_load_dialog.

    Геометрические Утилиты

    Одна группа функций дает возможность приложениям получить геометрическую информацию.
    AcutDistance () функция находит, что  расстояние между двумя точками, acutAngle () находит угол между линией, и X ось текущих ВЕРХНИХ РЕГИСТРОВ (в КООРДИНАТНОМ плане), и acutPolar () находит точку посредством полярных координат (относительно начальной точки). В отличие от большинства функций ObjectARX, эти функции не возвращают значение состояния. AcdbInters () функция находит пересечение двух линий; это возвращает RTNORM, если это находит точку, которая соответствует спецификации.
    ОБРАТИТЕ ВНИМАНИЕ В отличие от acedOsnap (), функции в этой группе просто вычисляют точку, линию, или угловые значения, и фактически не сделают запрос текущего рисунка.
    Следующий типовой кодовый фрагмент показывает некоторый простой, вызывает к геометрическим сервисным функциям.
    ads_point pt1, pt2;
    ads_point base, endpt;
    ads_real rads, length;
    .
    . // Инициализирует pt1 и pt2.
    .
    // Возвратить угол в КООРДИНАТНОМ плане текущих ВЕРХНИХ РЕГИСТРОВ, в радианах.
    rads = acutAngle (pt1, pt2);
    // Расстояние Возвращения в трехмерном пространстве{*пробеле*}.
    length = acutDistance (pt1, pt2);
    base [X] = 1.0; base [Y] = 7.0; base [Z] = 0.0;
    acutPolar (base, rads, length, endpt);
    Запрос к acutPolar () устанавливает endpt в точку, которая является тем же самым расстоянием от (1,7), поскольку pt1 - от pt2, и это - под тем же самым углом от X оси как угол между pt1 и pt2.

    Обзор

    Приложение ObjectARX - динамически загружаемая библиотека (DLL), использующая адресное пространство AutoCAD и посылающая ему прямые функциональные запросы. Можно добавлять новые классы к среде программы ObjectARX и экспортировать их для использования другими программами.
    Создаваемые ObjectARX-объекты  фактически неразличимы от встроенных объектов AutoCAD. Вы можете также расширить протокол ObjectARX,  прибавляя функции во
    время выполнения сеанса AutoCAD.
    Эта глава содержит краткий обзор библиотек классов AutoCAD и дает информацию для получения помощи по ObjectARX.
    Данное руководство предполагает, что Вы знакомы с AutoCAD  и объектно-ориентированным программированием на C++.

    Получение заказного класса ObjectARX

    Эта глава описывает, как использовать макрокоманды ObjectARX, чтобы упростить задачу получения заказного ObjectARX класса. Эти макрокоманды позволяют заказному классу участвовать в AcRxObject механизме идентификации типа во время выполнения. Если Вы не должны отличить ваш заказной класс во время выполнения, Вы можете использовать стандартный стиль образования C++, чтобы создать новый класс.
    ·
    Заказное Образование Класса
    · Идентификация Класса Во время выполнения
    · Макрокоманда Объявления Класса
    · Макрокоманды Выполнения Класса
    · Функция Инициализации Класса

    Наследование от AcDbObject

    Эта глава описывает, как получить заказной класс из AcDbObject. Это обеспечивает детальную информацию относительно регистраторов, четыре типа объектных ссылок  (интенсивно и мягких владельцев, и интенсивно и мягких указателей),  операций отмены и восстановления. Эта глава также обсуждает механизмы для объекта versioning. Описания в этой главе предполагают, что Вы знакомы с материалом, описанным в главе 5, “ Объекты Базы данных, ” и глава 11, при Наследовании Заказного ObjectARX Класса. ”
    · Перегрузка виртуальных функций AcDbObject
    · Реализация функций
    · Сохранение объектов в DWG и DXF файлах
    · Ссылки на объекты
    · Ссылки монопольного использования
    · Ссылки на указатели
    · Проблемы длинных транзакций для заказных объектов
    · Purge (Чистка)
    · Undo and Redo (Отмена и Восстановление)
    · subErase, subOpen, subClose, и subCancel
    · Пример Заказного Объектного Класса
    · Объектная Поддержка Версии

    Наследование от AcDbEntity

    Эта глава описывает, как получить класс пользователя из AcDbEntity, и включает определенные примеры отмены виртуальных методов, обеспеченных AcDbEntity классом.
    Перегрузка общих операции объекта, типа точек захвата объекта (гриппов), также обсуждена в этой главе.
    Материал в этой главе предполагает, что Вы знакомы с материалом, представленным в главе 6, “примитивы”; глава 11, при Наследовании Заказного ObjectARX Класса ”; и глава 12, “ Происходящий от AcDbObject. ”
    §
    Наследование заказных примитивов
    § Перегрузка общих функций примитива
    § Расширение функциональности примитива
    § Использование AcEdJig

    Расширение Протокола

    Все определения класса C++ установлены во времени компиляции.
    При нормальных обстоятельствах, если Вы записываете транслятор файла или команду редактирования, которая работает в ряде существующего AutoCAD классов, Вы должны переопределить все существующие классы, чтобы включить новый транслятор или редактирующие функции. И Вы были бы должны перетранслировать вашу библиотеку также как все приложения, которые используют это.
    Используя ObjectARX механизм расширения протокола, описанный в этой главе, Вы можете добавлять функциональные возможности к существующим классам ObjectARX во время выполнения, без любой модификации существующих классов и перетрансляции.
  • Определенное Расширение Протокола

  • Расширение Протокола Реализации

  • Расширение Протокола для MATCH-команд

  • Пример Расширения Протокола


  • Первичные базы данных

    База данных AutoCAD сохраняет объекты, которые составляют рисунок AutoCAD. Эта глава обсуждает ключевые элементы базы данных: объекты, таблицы идентификаторов и словарь имен объектов.
    Эта глава также представляет объектные маркеры(дескрипторы), объект IDs(цель), и протокол для открытия и заключительных объектов(целей) базы данных. Типовой код дает пример создания объектов, уровней, и групп, и добавления объектов(целей) к базе данных.
    · Краткий обзор базы данных AutoCAD
    · Основная база данных
    · Создание объекта в AutoCAD
    · Создание объекта в ObjectARX

    Глобальные сервисные функции ObjectARX

    Эта глава обсуждает некоторые общие характеристики ObjectARX глобальных сервисных функций. Для подробной информации относительно определенных функций, см. ObjectARX Ссылку.
    § Общие характеристики библиотечных функций ObjectARX
    § Переменные, Типы, и Значения, определенные в ObjectARX
    § Списки и Другие Динамически Размещенные Данные
    § Расширенные данные типы Исключительные Данные
    § Текстовые Строковые Проблемы Глобализации

    Точки ввода в процессе выполнения

    ObjectARX
    позволяет приложениям настраивать обработку входную точки. Приложение может связывать новые объектные точки  привязок и автопривязывать линии выравнивания с заказными и существующими примитивами, и может контролировать,  входная точка обрабатывает и изменяет входные точки. Эта глава обсуждает эти темы.
    § Заказные Режимы объектной привязки
    § Ввод направляют Управление

    Главa 23. COM, ActiveX Автоматизация и Менеджер свойств объекта

    Объектная модель программных компонентов Microsoft (COM) позволяет приложениям на платформе Windows связываться и обмениваться данными друг с другом.
    Вы можете обращаться к интерфейсам COM, обеспеченным другими ObjectARX-приложениями или любым приложением COM-enabled, выполняющимся на Windows.
    Дополнительно, используя COM с ObjectARX, Вы можете увеличивать ActiveX
    модель Автоматизации AutoCAD. Элементы, объекты, или примитивы, которые Вы выставляете, будут тогда доступны другим средам программирования типа Visual Basic для Приложений (VBA) и к особенностям AutoCAD типа Менеджера Свойств объекта (OPM).
    §
    Краткий обзор
    § Использование Объектов COM AutoCAD от ObjectARX и Других Сред
    § AutoCAD ActiveX Выполнение Автоматизации
    § Взаимодействующий с AutoCAD
    § Документ Блокировка
    § Создание Файла Системного реестра
    § Демонстрация Функциональных возможностей Автоматизации
    § Менеджер Свойства объекта API
    § Статические OPM Интерфейсы COM
    § Реализация Статические Интерфейсы OPM
    § Динамические Свойства и OPM

    API COM дизайн-центра AutoCAD

    AutoCAD имеет особенности, которые используют механизм COM, чтобы сделать запрос и изменить объекты. AutoCAD Дизайн-центр (ADC) использует механизм COM, чтобы обеспечить легко доступное содержание рисунка. Эта глава описывает интерфейсы COM, которые должны быть осуществлены вашим приложением для этого, чтобы участвовать и расширить AutoCAD Дизайн-центр r.
    § AutoCAD Дизайн-центр API
    § Требования Системного реестра для AutoCAD Дизайн-центр Компонент
    § Реализация Интерфейсы для AutoCAD Дизайн-центр
    § Настройка AutoCAD Дизайн-центр

    Библиотеки ObjectDBX

    ObjectDBX - преемник Отключенного DWG, и эта глава описывает изменения и расширения, что ObjectDBX SDK обеспечивает, наряду с описанием того, как осуществить приложения, использующие ObjectDBX.
  • Введение

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

  • Различия между ObjectDBX и ObjectARX

  • Локализация и XMX Файлы

  • Управление Транзакции

  • Создание Средства просмотра

  • Загрузка Требования

  • Установка ObjectDBX Библиотек

  • Советы и технические приемы

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


  • Библиотека графического интерфейса

    AutoCAD использует графическую библиотеку интерфейсов (AcGi), чтобы отобразить встроенные и заказные примитивы. Эта глава обсуждает черты примитива установки и примитивы использования, чтобы создать заказные графические примитивы. Для полного описания всех классов AcGi и их функций члена, см. ObjectARX Ссылку.
  • AcGi
    Краткий обзор

  • Установка Черт Примитива

  • Примитивы

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

  • Tessellation

  • Isolines

  • Преобразования

  • Использование границ обрезки в AcGi


  • Использование Библиотеки Геометрии

    Эта глава обсуждает основные использования AcGe библиотеки, которая обеспечивает множество классов для представления 2-ой и трехмерной геометрии. Эта библиотека предназначена для использования любым приложением Autodesk и часто используется AcDb и AcGi библиотеками в ObjectARX.
    § Краткий обзор AcGe Библиотеки
    § Использование Основных Типов Геометрии
    § Использование Линии и Классов Плана
    § Параметрическая Геометрия
    § Специальные Классы Оценки
    § Постоянные AcGe примитивы

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

    Эта глава показывает, как использовать AcBr библиотеку (libacbr.dll), чтобы обратиться к топологическим, геометрическим, и аналитическим данным, содержащимся в некоторых примитивах AutoCAD, типа solids, тел, и областей{*регионов*} (то есть объекты класса AcDb3dSolid, AcDbBody, и AcDbRegion), и бесчисленных производных типов (например, объекты класса AcDbPart, AcAsSurface, и совместимых определенных клиентом типов). С целью краткости, эта глава обращается к всем этим объектам все вместе как solids.
    § Краткий обзор
    § Домен{*область*}
    § Ограничения
    § Иерархия Классов
    § Топологические Объекты
    § AcBr Описания Класса
    § Перечислимые типы
    § Формирование Приложения
    Краткий обзор
    AcBr библиотека может использоваться со следующими примитивами AutoCAD:
    § AcDb3dSolid представляет твердый; это включает один или большее количество объемов.
    § AcDbRegion представляет плоскую поверхность; это могло бы содержать множественные компланарные поверхности.
    § AcDbBody - конкретный базовый класс для всех объектов контурного представления, не охваченных AcDb3dSolid или AcDbRegion, включая производные типы, определенные Autodesk Mechanical Desktop и клиентские приложения.
    § AcDbPart представляет твердый или тело листа в контексте трансляции{*блока*} или особенности в Autodesk Mechanical Desktop.
    § AcAsSurface представляет отдельную поверхность как тело листа в Autodesk Mechanical Desktop.

    AcBr библиотека обеспечивает доступ только для чтения к подмножеству данных моделирования, содержащихся в AutoCAD solids. Эти solids не требованы, чтобы быть базой данных, активной, и может быть создан способом из следующих путей:
    § команды создания объекта AutoCAD (типа СФЕРЫ), или эквивалентных сценариев AutoLISP.
    § Autodesk Механические команды создания Объекта оперативной памяти (типа ADREVOLVE), или эквивалентных сценариев AutoLISP.
    § Обращение команды EXPLODE AutoCAD на части или трансляции{*блоке*} в Autodesk Механический Рабочий стол.
    § внесение Файла, использующее ОТКРЫТЫЙ, DXFIN, ACISIN, ADSATIN, VDAFSIN, STEPIN, AMIDFIN, или IGESIN.
    § Программируемая реализация использования примитивов
    AcDb3dSolid:: createFrustum (), AcDb3dSolid:: createBox (),
    AcDb3dSolid:: createWedge (), AcDb3dSolid:: createSphere (),
    AcDb3dSolid:: createTorus (), AcDbRegion:: createFromCurves ().
    Типичные использования AcBr библиотеки включают следующее:
    § Передача примитива или данных подпримитива в ваше приложение для дисплея, анализа, или манипуляции.
    § Расположение специфических особенностей, представляющих интерес в твердом и запрашивающем для связанных данных, типа геометрии.
    § Передача данных примитива к другой системе моделирования (то есть обмен данных).
    § Поймавший в сети поверхностные данные в твердом для дисплея, анализа, или манипуляции.
    § Поддержка анализа (типа точки и сдерживания линии, ограничение блоков, и массовых свойств).

    Прикладные Основы ObjectARX

    Эта глава описывает, как записывать и выполнить приложение ObjectARX. Это перечисляет сообщения, которые пропускает в соответствии с AutoCAD к приложению ObjectARX и показывает, как приложение типично отвечает на те сообщения. Эта глава также обсуждает регистрацию новых команд, как загружать и разгружать приложение по запросу AutoCAD, особенности загрузки и обработку ошибок.
    · Создание приложения ObjectARX
    · Пример приложения
    · Регистрация новых команд
    · Загрузка приложения ObjectARX
    · Разгрузка приложения ObjectARX
    · Запрос на загрузку
    · ARX Command
    · Выполнение приложения ObjectARX

    Операции базы данных рисунка

    Эта глава описывает основной протокол базы данных, включая, как создать базу данных, как читать в чертежном файле, и как сохранить базу данных. Wblock и операции вставки также описаны здесь. Для более детальной информации относительно deepClone и wblock операций, см. главу 18, при Глубоко Имитации. ”
  • Начальная База данных

  • Создание и Начальная загрузка Базы данных

  • Сохранение Базы данных

  • wblock Операция

  • Вставка Базы данных

  • Установка Текущих Значений Базы данных

  • Пример Операций Базы данных

  • Длинные транзакции

  • Внешние ссылки

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

  • Рисунок Итоговой Информации

  • Из прошлого, сохраненного программным обеспечением Autodesk


  • Объекты Базы данных

    Эта глава описывает темы, которые касаются всех объектов базы данных AutoCAD, включая объекты, записи таблицы идентификаторов и словари. Главные включенные концепции открывают и закрывают объекты, управляя объектами в памяти, монопольном использовании объекта, и расширяя объект, используя xdata или словарь расширения объекта. Другие общие операции на объектах, типа записи в файл и стирания, также обсуждены.
  • Открытие и Закрытие Объектов Базы данных

  • Удаляющие Объекты

  • Монопольное использование Базы данных Объектов

  • Добавление Объектно - определенных Данных

  • Стирающие Объекты

  • Объектная Запись в файл


  • Примитивы

    Эта глава описывает примитивы — объекты базы данных с графическим представлением. Это перечисляет свойства и операции, все примитивы имеют в общем{*обычном*}. Примеры показывают, как создать блоки, вставки, и комплексные примитивы, и как выбирать и высветить подпримитивы.
  • Определенные Примитивы

  • Монопольное использование Примитива

  • Выпуск AutoCAD 12 Примитивов

  • Общие{*обычные*} Свойства Примитива

  • Общие{*обычные*} Функции Примитива

  • Создание Образцов Примитивов AutoCAD

  • Комплексные Примитивы

  • Доступ Системы координат

  • Функции Кривой

  • Связывающиеся Гиперсвязи с Примитивами


  • Контейнерные Объекты

    Эта глава описывает контейнерные объекты, используемые в операциях базы данных AutoCAD: таблицы идентификаторов, словари, группы, и xrecords. Как часть любого рисунка, AutoCAD создает установленный набор таблиц идентификаторов и названного объектного словаря, который содержит два других словаря, MLINE стиль и словари ГРУПП.
    Примеры главы демонстрируют, как добавить входы к таблицам идентификаторов, словарям, и группам, и как сделать запрос содержания этих контейнеров, использующих iterators.
    Они также показывают, как создавать и использовать ваши собственные словари и xrecords, чтобы управлять данными прикладной программы и объектами. Для описания словаря расширения объекта AcDbObject, см. главу 5, “ Объекты Базы данных. ”
    § Сравнение Таблиц идентификаторов и Словарей
    § Таблицы идентификаторов (Symbol Tables)
    § Словари (Dictionaries)
    § Размещения (Layouts)
    § Xrecords

    MFC

    Библиотека фундаментальных классов Microsoft (MFC) позволяет разработчику осуществлять стандартные интерфейсы пользователя быстро. ObjectARX среда обеспечивает набор классов, что разработчик может использовать, чтобы создать MFC-ОСНОВАННЫЕ интерфейсы пользователя, которые ведут себя и появляются как встроенные интерфейсы пользователя Autodesk. Эта глава описывает, как использовать MFC
    библиотеку как часть Приложения ObjectArx.
    §
    Введение
    § Использование MFC с Приложениями ObjectArx
    § Приложения ObjectArx с Динамически Связанным MFC
    § Встроенная MFC Поддержка Интерфейса пользователя
    § Использование AdUi и AcUi с VC
    ++ AppWizard

    Наборы выборов, примитивы и функции таблиц идентификаторов

    Глобальные функции, описанные в этой главе обрабатывают наборы выбора, рисуют примитивы и таблицы идентификаторов. См. Руководство Настройки AutoCAD для основной информации на этих темах.
    § Набор выборов и имена примитивов
    § Обработка Наборов Выбора
    § Имя Примитива и Функции Данных
    § Доступ Таблицы идентификаторов

    Глобальные Функции для Взаимодействия с AutoCAD

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

  • Получение Ввода Пользователя

  • Преобразования

  • Обработка Символьного типа

  • Преобразования Системы координат

  • Управление Дисплея

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

  • Универсальное сопоставление


  • Полномочные Объекты (Proxy)

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

  • Цикл Жизни прокси-объекта

  • Прокси-объект для пользователя

  • Отображение прокси-примитивов

  • Редактирование прокси-примитивов

  • Разгрузка приложения


  • Уведомления

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

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

  • Руководящие принципы использования уведомлений


  • Многодокументная среда

    AutoCAD поддерживает многодокументную среду (MDI), который позволяет Вам иметь больше чем один рисунок, загруженный сразу на единственной сессии AutoCAD. Эта глава описывает, как работать с MDI в вашем ObjectARX-приложении.
    § Краткий обзор
    § Терминология
    § SDI Переменная Системы
    § Уровни Совместимости
    § Взаимодействующий с Множественными документами
    § Уведомление События Документа
    § Специфические для приложения Объекты Документа
    § Неповторно используемые Команды
    § Команды Много-документа
    § Отключение Переключения Документа
    § Прикладной Контекст Выполнения
    § Отмена Базы данных и Средства Управления Транзакции
    § Документированные - независимые Базы данных
    § MDI-ЗНАЮЩИЙ Приложение Примеры.

    Управление транзакцией

    Эта глава описывает операционную модель, которая может использоваться, чтобы работать на объектах AcDb. В этой модели, множественные операции на множественных объектах сгруппированы вместе в одну атомную операцию, вызвал сделку.
    Транзакции могут быть вложены и могут быть закончены или прерван на усмотрение клиента. Эта модель может использоваться в конъюнкции с регулярным " в объект" открытый и близкий механизм, описанный в главе 5, “ Объекты Базы данных. ”
    §
    Краткий обзор Управления Транзакции
    § Менеджер Транзакции
    § Вложение транзакций
    § Границы Транзакции
    § Получение Указателей на Объекты в Транзакции
    § Недавно Созданные Объекты и транзакции
    § Совершают разовые Руководящие принципы
    § Отмена и транзакции
    § Смешивание Модели Транзакции с Открытым и Близким Механизмом
    § транзакции и Графическое порождение
    § Реакторы Транзакции
    § Пример Вложенных транзакций

    Глобальные функции сохранения

    ObjectARX также содержит две глобальных функции для сохранения рисунков:
    Acad::ErrorStatus
    acdbSaveAsR13(
    AcDbDatabase* pDb,
    const char* fileName);
    Acad::ErrorStatus
    acdbSaveAsR14(
    AcDbDatabase* pDb,
    const char* fileName);
    Обе функции принимают указатель базы данных и имя файла, и выписывают рисунок в Выпуске AutoCAD 13 или Выпускают 14 формата DWG, соответственно.

    Глобальные идентификаторы и файлы заголовка



    Файл Заголовка

    Глобальные Определенные Функции

    gepnt2d.h

    AcGePoint2d::kOrigin

    gemat2d.h

    AcGeMatrix2d::kIdentity

    gevec2d.h

    AcGeVector2d::kIdentity
    AcGeVector2d::kXAxis
    AcGeVector2d::kYAxis

    geline2d.h

    AcGeLine2d::kXAxis
    AcGeLine2d::kYAxis

    gepnt3d.h

    AcGePoint3d::kOrigin

    gemat3d.h

    AcGeMatrix3d::kIdentity

    gevec3d.h

    AcGeVector3d::kIdentity
    AcGeVector3d::kXAxis
    AcGeVector3d::kYAxis
    AcGeVector3d::kZAxis

    geline3d.h

    AcGeLine3d::kXAxis
    AcGeLine3d::kYAxis
    AcGeLine3d::kZAxis

    geplane.h

    AcGePlane::kXYPlane
    AcGePlane::kYZPlane
    AcGePlane::kXZPlane

    gegbl.h

    AcGeContext::gOrthoVector()

    AcGeContext:: gOrthoVector - указатель на функцию что, учитывая вектор, вычисляет произвольный вектор, который является перпендикулярным к этому. Вы можете заменять вашу собственную функцию на данную функцию.
    Допуски
    Много методов принимают значение допуска как один из их параметров. Это значение имеет AcGeTol класс и всегда имеет значение по умолчанию, как определено в AcGeContext:: gTol. Функции типа isClosed () и isPlanar () вычисляют,являются ли точки начала и оконечные точки в пределах определенного допуска перед возвращением Булева значения. Вы можете изменять допуск для одного специфического функционального запроса, или Вы можете изменять глобальное значение допуска.
    AcGeTol класс обеспечивает две функции для установки допуска для точек и векторов:
    void
    setEqualPoint(double);
    void
    setEqualVector(double);
    AcGeTol класс также обеспечивает две функции для получения допуска для точек и векторов:
    double equalPoint() const;
    double equalVector() const;
    EqualPoint и equalVector значения допуска используются следующим образом:
    § Две точки, p1 и p2, являются равным если
     ( p1 - p2) .length () < = equalPoint
    § Два вектора, v1 и v2, являются равным если
    ( v1 - v2) .length () < = equalVector
    § Два вектора, v1 и v2, являются параллельным если
    ( v1/v1.length () - v2/v2.length ()) .length () < equalVector
    ИЛИ (v1/v1.length () + v2/v2.length ()) .length () < equalVector
    § Два вектора, v1 и v2, являются перпендикулярным если
    abs((v1.dotProduct(v2))/(v1.length()*v2.length())) < = equalVector
    § Две линии или лучи - параллельный (перпендикуляр), если их направленные векторы - параллельный (перпендикуляр)
    § Две линии равен, если точки в параметре 0 равны, и их направления равны
    ОБРАТИТЕ ВНИМАНИЕ, что эти правила подразумевают, что две линии - близко к друг другу как точечные множества в части пространства моделирования диаметра diam только, если допуск equalVector установлен более плотным чем equalPoint/diam.

    Глобальные Итоговые Информационные Функции

    ObjectARX содержит несколько глобальных функций для доступа к итоговой информации:
    Acad:: ErrorStatus
    AcdbGetSummaryInfo (
    AcDbDatabase* pDb,
     AcDbDatabaseSummaryInfo*& PInfo);
    Acad:: ErrorStatus
    AcdbPutSummaryInfo (
    Константа
    AcDbDatabaseSummaryInfo* pInfo);
    AcDbSummaryInfoManager*
    AcdbGetSummaryInfoManager ();
    Для получения дополнительной информации на этих функциях, см. ObjectARX Ссылку{*справочники*}.

    Графические Функции Нижнего уровня

    Следующие графические функции не могут быть вызваны, в то время как диалоговое окно активно:
    §
    acedGrVecs ()
    § acedGrDrag ()
    § acedGrRead ()
    § acedGrText ()
    § acedGrDraw ()
    § acedGrText ()

    Графическое перемещение Наборов Выбора

    Функция acedDragGen () запрашивает пользователя перетаскивать группу отобранных объектов, как показано в следующем примере:
    int rc;
    ads_name ssname;
    ads_point return_pt;
    // Prompt the user for a general entity selection.
    if (acedSSGet(NULL, NULL, NULL, NULL, ssname) == RTNORM)
    // The newly selected entities
    rc = acedDragGen(ssname,
    "Drag selected objects", // Prompt
    0, // Display normal cursor (crosshairs)
    dragsample, // Transformation function
    return_pt); // Set to the specified location.
    Четвертый параметр указывает на функцию, которая делает преобразование примитива. См. “ Преобразование Наборов Выбора ” на странице 211 для примеров dragsample () и acedDragGen ().

    Границы транзакции

    Поскольку Вы, не система, отвечаете за старт, окончание, или транзакции прерывания выполнения, важно знать операционные границы. Операционная граница - время между началом и концом или аварийным прекращением работы транзакции.
    Рекомендуется, чтобы Вы ограничили{*заключили*} вашу границу к самой маленькой возможной области{*контексту*}. Например, если Вы запускаете транзакцию в функции, пробуете заканчивать или прервать транзакцию прежде, чем Вы возвращаетесь от той функции, потому что Вы не можете иметь знание транзакции вне функции. Вы не должны следовать за этим правилом, если Вы поддерживаете некоторый глобального менеджера для ваших операционных действий, но Вы все еще ответствены за прерывание выполнения или окончание всех транзакций, которые Вы запускаете.
    Множественные приложения могут использовать операционное управление для их работы, и операции на объектах совершены{*переданы*} в конце наиболее удаленной транзакции.
    Поэтому, граница команды AutoCAD - то, насколько Вы можете протягивать границу ваших транзакций. Когда команда концы, там не должна быть никакие активные транзакции. Если имеются любые активные транзакции (операционный стек не пуст) когда команда концы, AutoCAD прервется. Как исключение, транзакции могут все еще быть активны, когда acedCommand () или прозрачная команда концы, но они должны весь быть решенными, когда основная команда концы и AutoCAD возвращается Приглашению ко вводу команды.
    Это - вообще хорошая идея запустить транзакцию, когда одна из ваших функций вызвана как часть команды, зарегистрированной Вами и концом это, когда Вы возвращаетесь от той функции. Вы можете обобщать это к всем командам в AutoCAD, используя AcEditorReactor:: commandWillStart () и AcEditorReactor:: commandEnded () уведомления, но имеются некоторые команды, которые не должны быть проведены. Следующие команды не должны быть проведены:
    §
    ARX
    § DXFIN
    § INSERT
    § NEW
    § OPEN
    § PURGE
    § QUIT
    § RECOVER
    § REDO
    § SAVE
    § SCRIPT
    § U
    § UNDO
    § XREF

    Группы и Словарь Группы

    Группа - контейнерный объект, который обслуживает{*поддерживает*} упорядоченную{*заказанную*} коллекцию примитивов базы данных. О группах можно думать как названный постоянными наборами выбора. Они не имеют связи{*ссылки*} монопольных использований к примитивам, которые они содержат.
    Когда примитив стерт, это автоматически удалено из групп, которые содержат это. Если примитив нестерт, это автоматически повторно вставлено в группу.
    Используйте AcDbGroup:: newIterator () функция, чтобы получить iterator и шаг через примитивы в группе. AcDbGroup класс также обеспечивает функции для добавления в конец и prepending примитивов к группе, вставка примитивов по специфическому индексу в группе, удаление примитивов, и передачи примитивов от одной позиции в группе к другому. См. AcDbGroup в ObjectARX Ссылке.
    Вы можете также назначать свойства на всех членов группы, использующей
    setColor (), setLayer (), setLinetype (), setVisibility (), и
    setHighlight () функции AcDbGroup класса. Эти операции имеют тот же самый эффект как открытие каждого примитива в группе и установке ее свойства непосредственно.
    Группы должны всегда сохраняться в словаре ГРУППЫ, который может быть получен следующим образом:
    AcDbDictionary* pGrpDict =
    acdbHostApplicationServices()->working Database()->
    getGroupDictionary(pGroupDict, AcDb::kForWrite);
    Альтернативный способ получить словарь ГРУППЫ состоит в том, чтобы искать “ACAD_GROUP” в словаре имен объектов.
    Следующие функции - часть приложения, что первые подсказки пользователь, чтобы выбрать некоторые примитивы, которые помещены в группу по имени “ASDK_GROUPTEST”. Тогда это вызывает функцию removeAllButLines () чтобы выполнить итерации по группе и удалять все примитивы, которые - не линии. Наконец, это изменяет{*заменяет*} остающиеся примитивы в группе к красному.
    void
    groups()
    {
    AcDbGroup *pGroup = new AcDbGroup("grouptest");
    AcDbDictionary *pGroupDict;
    acdbHostApplicationServices()->workingDatabase()

    ->getGroupDictionary(pGroupDict, AcDb::kForWrite);

    AcDbObjectId groupId;

    pGroupDict->setAt("ASDK_GROUPTEST", pGroup, groupId);

    pGroupDict->close();

    pGroup->close();

    makeGroup(groupId);

    removeAllButLines(groupId);

    }

    // Prompts the user to select objects to add to the group,

    // opens the group identified by "groupId" passed in as

    // an argument, then adds the selected objects to the group.

    //

    void

    makeGroup(AcDbObjectId groupId)

    {

    ads_name sset;

    int err = acedSSGet(NULL, NULL, NULL, NULL, sset);

    if (err != RTNORM) {

    return;

    }

    AcDbGroup *pGroup;

    acdbOpenObject(pGroup, groupId, AcDb::kForWrite);

    // Traverse the selection set, exchanging each ads_name

    // for an object ID, then adding the object to the group.

    //

    long i, length;

    ads_name ename;

    AcDbObjectId entId;

    acedSSLength(sset, &length);

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

    acedSSName(sset, i, ename);

    acdbGetObjectId(entId, ename);

    pGroup->append(entId);

    }

    pGroup->close();

    acedSSFree(sset);

    }

    // Accepts an object ID of an AcDbGroup object, opens it,

    // then iterates over the group, removing all entities that

    // are not AcDbLines and changing all remaining entities in

    // the group to color red.

    //

    void

    removeAllButLines(AcDbObjectId groupId)

    {

    AcDbGroup *pGroup;

    acdbOpenObject(pGroup, groupId, AcDb::kForWrite);

    AcDbGroupIterator *pIter = pGroup->newIterator();

    AcDbObject *pObj;

    for (; !pIter->done(); pIter->next()) {

    pIter->getObject(pObj, AcDb::kForRead);

    // If it is not a line or descended from a line,

    // close it and remove it from the group. Otherwise,

    // just close it.

    //

    if (!pObj->isKindOf(AcDbLine::desc())) {

    // AcDbGroup::remove() requires that the object

    // to be removed be closed, so close it now.

    //

    pObj->close();

    pGroup->remove(pIter->objectId());

    } else {

    pObj->close();

    }

    }

    delete pIter;

    // Now change the color of all the entities in the group

    // to red (AutoCAD color index number 1).

    //

    pGroup->setColorIndex(1);

    pGroup->close();

    }

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

    Чтобы тянуть{*рисовать*} себя, каждый примитив делает запросы к графическим примитивам типа ломаных линий, кругов, и дуг, содержащихся в AcGi библиотеке. Любой класс, полученный из AcDbEntity может связывать систему графики (GS) маркер с векторами дисплея, которые это использует, чтобы тянуть{*рисовать*} себя. Каждый подкласс примитива управляет, где это вставляет его GS маркеры. Когда пользователь выбирает примитив, GS маркер используется, чтобы выделить, которая часть примитива была выбрана.
    Solids полученный из AcDb3dSolid составлены из вершины, граней, и лиц.
    Каждый из этих элементов может быть идентифицирован GS маркером. Создатель класса примитива решает, где GS маркеры должны быть вставлены, в зависимости от того, что является наиболее естественным для примитива. Поле, например, создает GS маркер для каждой строки, имел обыкновение тянуть{*рисовать*} поле. Цилиндр создает три GS маркеры — один для его вершины, основания, и вне лиц.
    Примитив составлен из подпримитивов следующего типа: вершина, край, или лицо. В настоящее время, единственные примитивы, которые поддерживают подпримитивы - тела, области{*регионы*}, solids, и mlines. Используйте getSubentPathsAtGsMarker () функция, чтобы получить пути к подпримитивам, которые связаны с частностью GS маркер.
    Больше чем один подпримитив могут быть связаны с одиночным маркером. В случае поля, например, маркер 4 идентифицирует более низкий передний край поля.
    Если Вы просите о вершине, связанной с этим маркером, две вершина, которая формируется,  оконечные точки этой строки возвращены. Если Вы просите о гранях, связанных с этим маркером, один примитив — строка — возвращен. Если Вы просите о лицах, связанных с этим маркером, данные для лицевой поверхности и нижней поверхности поля возвращены.

    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)), вы будете должны сделать запрос блока или уровня для фактического номера цвета.

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

    Кривые имеют следующие характеристики:
    §
    Ориентация
    § Периодичность
    § Замкнутое выражение
    § 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;
    };

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

    Каждый класс в 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, “ Расширение Протокола. ”

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

    В 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 для подробной информации относительно заказных меню.

    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 для ваших заказных объектов.

    Использование 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, чтобы работать на комплексных объектах типа ломаных линий.

    Использование 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 ())

    Использование 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
    #include
    #include
    // 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 могут использоваться.

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

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

    Использование Класса 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:
    §
    Твердая копия
    § Меню
    § Опции

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

    Чтобы использовать функциональные возможности расширения протокола, Вы должны получить объект описателя класса для специфического класса. Как только Вы получили указатель на объект описателя класса, Вы можете вызывать любой из методов для того класса. Следующее - пример использования 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() функция. Чтобы добавлять или удалять переходный реактор к объекту уведомителя, объект может быть открытый в любом состоянии (чтение, записывать, или уведомлять).

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

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

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

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

    Заказной объектный  менеджер привязки обрабатывает регистрацию заказных режимов объектной привязки. Это может использоваться, чтобы добавлять, удалять, активизировать, и дезактивировать заказные режимы объектной привязки. Заказной объектный поспешный менеджер также может использоваться, чтобы сделать запрос, зарегистрирован ли указанный режим объектной привязки и активный.
    Имеется единственный заказной объектный менеджер привязок для всего приложения. После того, как зарегистрирован, заказной режим объектной привязки может применяться в любом открытом документе.
    Следующая глобальная функция может использоваться, чтобы обратиться к заказному объектному менеджеру:
    AcDbCustomOsnapManager *
    acdbCustomOsnapManager() const;
    Как правило, заказные режимы объектной привязки зарегистрированы, когда приложение загружено и удалены, когда приложение разгружено, хотя они могут быть зарегистрированы и удалены в любое время.

    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 () функция возвращает значение атрибута в строковом параметре (значение). Поскольку эта функция устанавливает значение строки, Вы должны разместить пространство для этого, как показано в предшествующем примере.

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

    Имеются два типа контекстов выполнения, приложения и документа. Все зарегистрированные команды и реакторные повторные вызовы выполнены в пределах контекста выполнения документа. Сообщения 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,
    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 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 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
    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 Пример

    Новые параметры 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 или это будет представлено третьими лицами, может страдать от этой проблемы, особенно, если один из их супер-классов изменил{*заменил*} данные.

    Класс 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 файлов.

    Классы 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

    Классы Сети

    Объекты Сети никогда не сформированы непосредственно пользователем, кроме где отмечено в ObjectARX Ссылке. Они возвращены запросами обхода сети.
    Классы сети включают следующее:
    §
    AcBrMeshEntity
    § AcBrMesh
    § AcBrMesh2d
    § AcBrElement
    § AcBrElement2d
    § AcBrNode
    § AcBrMesh2dFilter
    § AcBrMeshControl
    § AcBrMesh2dControl

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

    Отношения между объектами сохранены в объекте как компонент данных 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


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

    Если Вы клонируемые набор объектов от различных владельцев, вы будете должны делить набор объектных 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 ())


    Выпуск 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-приложения, которые делают явные предположения относительно предела строковой длины имен таблицы идентификаторов, и НА ТЕКСТОВЫЕ примитивы воздействуют символы " из страницы коды ".

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

    Наконец, 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. Команда состоит из последовательности программы, выполненной как логический модуль работы, которая может требоваться пользователем или одним из AutoCAD, пишущего сценарий двигатели. Независимо от того, какой конструкция используется, команда может быть уничтожена независимо от других действий, выполненных в течение операции системы.
    Определенно для API MDI, команда - последовательность кода, который начинается,  блокируя документ и концы,  разблокируя документ. В общих{*обычных*} случаях, эта блокировка и разблокирование будет выполнена ObjectARX, но в течение других времен,  приложение должно делать блокировку и разблокирование непосредственно. Все после конструкций AutoCAD - команды:
    §
    AutoCAD встроенные команды.
    § Встроенные команды, выполненные непосредственно от командного процессора, типа F2 для экрана изменения. Это включает функцию и клавиши CTRL.
    § обращения функции AutoLISP, которые могут быть определены или в AutoLISP или в ObjectARX-приложении, используя acedDefun ().
    § команды программы External, определенные в acad.pgp.
    § AcEd-зарегистрированные команды, зарегистрированные из AutoCAD.
    § Действия, принятые от немодального окна диалога или некоторого другого внешнего процесса, типично, которому оказывает гостеприимство ObjectARX-приложение.
    § набор действий, принятых от приложения ActiveX во внешнем процессе.
    § Действия, принятые от VBA до интерфейса ActiveX.
    § Щелкают правой кнопкой мыши обращения меню контекста.

    Команды 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 ().


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

    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/?/

    : 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-приложения, переносящие немодальные диалоги будут требоваться, чтобы блокировать и разблокировать документы, явно чтобы взаимодействовать с их базами данных.

    Контроль относительно Графики Нижнего уровня и Ввода пользователя

    Некоторые функции обеспечивают прямой доступ к экрану графики AutoCAD и устройствам ввода данных. Они позволяют ObjectARX-приложениям использовать часть дисплея и средств взаимодействия пользователя, включенных В AutoCAD.
    AcedGrText () функциональный текст дисплеев в состоянии или областях меню, с или без высвечивания{*увеличения яркости*}. AcedGrDraw () функция тянет{*рисует*} вектор в текущей области просмотра, с контролем над цветом и высвечиванием{*увеличением яркости*}. AcedGrVecs () функция тянет{*рисует*} множественные векторы. AcedGrRead () функциональные возвращения ввод пользователя “сырья”, ли от клавиатуры или устройства управления позицией; если запрос к acedGrRead () позволяет трэкинг, функция возвращает цифровые координаты, которые могут использоваться для перемещения.
    ПРЕДУПРЕЖДЕНИЕ! Поскольку эти функции зависят от кода в AutoCAD, их операция может изменяться от выпуска. Приложения, которые вызывают эти функции, не могут быть восходяще совместимы. Также, они зависят от текущей аппаратной конфигурации. В частности приложения, которые вызывают acedGrText () и acedGrRead (), вряд ли,  будут работать тот же самый на всех конфигурациях, если разработчик не использует их как описано ранее, чтобы избежать аппаратно-зависимых особенностей.
    Эти функции не делают почти никакое сообщение ошибки и могут повреждать графическое экранное устройство отображения (см. пример для способа установить эту проблему).
    Следующее повреждение при смене графического экранного устройства отображения вызвано неправильным обращением к acedGrText (), acedGrDraw (), или acedGrVecs ().
    acedGrText (-3, NULL, 0);
    acedRedraw (NULL, 0);
    Параметры к acedGrText () имеют следующие значения: -3 восстановление стандартного текста, NULL == никакой новый текст, и 0 == никакое высвечивание. Параметры к acedRedraw() имеют следующие значения: NULL == все примитивы, и 0 == вся область просмотра.

    Контроль Точки ввода

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

    Копирование Массива примитивов

    Следующая функция эквивалентна вызову команды WBLOCK и затем использование опции, чтобы выбрать определенные объекты и определять арифметическую запятую вставки:
    Acad::ErrorStatus
    AcDbDatabase::wblock(AcDbDatabase*& newDb,
    const AcDbObjectIdArray& idArray,
    const AcGePoint3d* point);
     Эта функция создает новую базу данных, которая включает объекты, указанные в idArray параметре. Объекты, которые могут быть в образцовых пространственных или бумажных пространственных блочных отчетах{*записях*} таблицы входной базы данных, помещены в образцовое пространство{*пробел*} новой базы данных. Также включенный в новую базу данных - объекты, принадлежащие или упомянутый теми объектами, также как владельцами тех объектов. Указанный пункт{*точка*} - пункт{*точка*} начала координат, во внешних координатах, для нового рисунка (то есть это - арифметическая запятая вставки в образцовом пространстве{*пробеле*} новой базы данных).

    Копирование Названного Блока

    Следующая функция эквивалентна вызову команды WBLOCK с названием{*именем*} блочного определения:
    Acad:: ErrorStatus
     AcDbDatabase::wblock(AcDbDatabase*& NewDb,
    AcDbObjectId recordId);
    RecordId параметр представляет блочный запись таблицы во входной базе данных.
    Объекты в этом блочном записи таблицы скопированы в образцово - пространственный блочный запись таблицы новой базы данных. Ядро вставки новой базы данных - блочное начало координат записи таблицы.

    Краткий обзор AcGe Библиотеки

    AcGe библиотека включает широкий набор классов для представления обычно используемая геометрия, типа точек, линий, кривых, и поверхностей. Это обеспечивает общее представление для геометрии, которая может использоваться любым приложением Autodesk. Библиотека вполне математическая; хотя его классы не имеют дело непосредственно с базой данных или с графикой, многие из его классов используются AcDb и AcGi библиотеками.
    Иерархия классов для AcGe библиотеки показывается следующим образом:
    Краткий обзор AcGe Библиотеки
    AcGe библиотека обеспечивает, и простые и комплексные классы геометрии. Простые линейные классы алгебры включают точку, вектор, матрицу, 2-ые и трехмерные линейные классы примитива, и плоские классы примитива. Комплексные классы включают классы кривой, типа сплайнового примитива, и поверхностных классов, типа поверхностей НЕОДНОРОДНОГО РАЦИОНАЛЬНОГО В-СПЛАЙНА.
    Иерархия классов предлагает отдельные классы для 2-ой и трехмерной геометрии. Это упрощает программирование,  ясно отличая 2-ую параметрически - пространственную геометрию от трехмерной геометрии пространства моделирования. Из-за этого различия, Вы не можете неосторожно смешивать 2-ые и трехмерные примитивы в той же самой операции.
    Библиотека включает множество основных типов, типа AcGePoint3d, AcGeVector3d, и AcGeMatrix3d, которые имеют общественные компоненты данных для быстрого и эффективного доступа. Эти простые классы обычно используются другими библиотеками также как классами AcGe, полученными из AcGeEntity2d и AcGeEntity3d.
    Контроль соответствия типов Во время выполнения предусмотрен все классы, полученные из AcGeEntity2d и AcGeEntity3d. Каждый класс обеспечивает type() функцией, которая возвращает класс объекта и isKindOf () функция, которая возвращается, имеет ли объект специфический класс (или класс, полученный из того класса).
    Два примитива рассматриваются равными, если они имеют тот же самый тип и представляют то же самое точечное множество. Кривые и поверхности рассматриваются равными только, если их параметризация - тот же самый.

    Краткий обзор Базы данных AutoCAD

    Рисунок AutoCAD - коллекция объектов, сохраненных в базе данных. Некоторые из основных объектов базы данных - объекты, таблицы идентификаторов, и словари. Объекты - специальный вид базы данных, имеют графическое представление в пределах рисунка AutoCAD. Строки, круги, дуги, текст, solids, области(регионы), сплайны, и эллипсы - примеры объектов. Пользователь может видеть объект на экране и может управлять им.
    Таблицы идентификаторов и словари - контейнеры, имел обыкновение сохранять объекты  базы данных. Оба контейнерных объекта отображают строку имени к объекту базы данных. База данных AutoCAD включает фиксированный набор таблиц идентификаторов, каждая из которых содержит образцы специфического класса отчета таблицы идентификаторов. Вы не можете прибавлять новую таблицу идентификаторов к базе данных. Примеры таблиц идентификаторов - таблица уровня (AcDbLayerTable), который содержит отчеты таблицы уровня, и блочную таблицу (AcDbBlockTable), который содержит блочные отчеты таблицы. Все объекты AutoCAD принадлежат блочным отчетам таблицы.
    Словари обеспечивают более универсальный контейнер для сохранения объектов, чем таблицы идентификаторов. Словарь может содержать любой объект типа AcDbObject или подкласса этого. База данных AutoCAD создает словарь называемый названным объектным словарем, когда это создает новый рисунок. Названный объектный словарь может просматриваться как главное “оглавление” для всех словарей, связанных с базой данных. Вы можете создавать новые словари в пределах названного объектного словаря и прибавлять новая база данных. Следующий рисунок показывает ключевые компоненты базы данных AutoCAD.
    Краткий обзор Базы данных AutoCAD
    В течение сеанса редактирования Вы можете получить базу данных для текущего рисунка,  вызывая следующую глобальную функцию:
    acdbHostApplicationServices()->workingDatabase()

    Краткий обзор управления транзакциями

    Операционная модель формирует множественные операции на множественных объектах несколькими клиентами, поскольку одна атомная операция вызвала транзакцию. Внутри операционной границы, клиенты могут получить объектные указатели от объекта IDs. Объектные указатели, таким образом полученные имеют силу, пока транзакция не закончена или прервана клиентом. Если транзакция закончена успешно, операции на объектах совершены{*переданы*}. Если транзакция прервана, операции на объектах отменены.
    Действие на объектах, использующих эту парадигму имеет несколько преимуществ по регулярному открытому и близкому механизму, описанному в главе 5, “ Объекты Базы данных. ” Открытый и близкий механизм подходящий для простых операций на единственном{*отдельном*} объекте или маленькой группе объектов. Однако, имеются некоторые ограничения на открывающиеся объекты этот путь. Например, если объект открытый для чтения, Вы не можете открывать это для записи в то же самое время. Если объект открытый для записи, Вы не можете открывать это для записи второй раз. Для списка ошибок конфликта, связанных с открытым и близким механизмом, см. главу 5, “ Объекты Базы данных. ” Операционная модель более снисходительна, и получение объектных указателей от объекта IDs для специфического режима обычно преуспевает, если объект связан с транзакцией.
    В зависимости от вашего приложения, могут иметься другие недостатки к использованию открытого и закрывать механизм. Если ваше приложение открывает и закрывает тот же самый объект неоднократно в ходе одной операции — например, команда — вы будете нести серьезные неэффективность из-за этого множителя, открывает и закрывается. Множество отнимающих много времени операций связано с закрытием объекта. Если Вы открываете объект для записи, измените это, и затем закройтесь, это, записи отмены модификации совершено{*передано*} файлу отмены, графика для объекта сгенерирована, и уведомления обстреляны. Все эти операции
    Выполненный каждый раз объект закрыт. Если Вы проводите вашу операцию и получаете указатель на объект, используя транзакцию, все действия, упомянутые выше случаются только однажды, в конце транзакции. Результат - улучшенная эффективность и меньший файл отмены, потому что число записей, входящих в файл отмены уменьшен.
    Также, если Вы имеете сложную сеть, где объекты обращаются{*относятся*} к друг другу объектом ID, Вы хотите быть способными получить указатель на объект в любом модуле вашей программы без того, чтобы волноваться, если другой модуль или другое приложение открывают тот объект. Эти действия - только возможное использование операционная модель потому что операции группы транзакций и позволяют получать указатели от объекта IDs поперек границ модуля.

    Краткий обзор уведомлений

    Когда событие происходит в системе, некоторых объектах, вызванных{*названных*} уведомителях, автоматически передайте событие к другим объектам. Например, когда копии пользователя, стирания, или изменяют объект или когда пользователь выпускает команду UNDO ИЛИ REDO, соответствующее уведомление для каждого события автоматически вызвано.
    Объекты, получающие события - вызванные{*названные*} реакторы. Реактор должен быть явно добавлен к реакторному списку уведомителя прежде, чем это может получать события от уведомителя. Данный уведомитель может иметь множество реакторов в его реакторном списке. Определение класса реактора включает различные функции уведомления. Когда событие происходит, уведомитель автоматически вызывает соответствующую функцию уведомления каждого реактора в его реакторном списке.
    Использовать реактор в приложении
    1 Получают новый реакторный класс и осуществляют функции уведомления для событий, ваш реактор ответит на.
    2 Инициализируют реактор.
    3 Добавляют реактор к реакторному списку уведомителя.
    При закончено использование реактора
    1 Удаляют реактор из реакторных списков всех уведомителей, к которым это было добавлено.
    2 Удаляют реактор (если это не объект резидента базы).
    Использование реакторов требует подклассов создания реакторных классов или классов AcDbObject. Эта глава предполагает, что Вы знакомы с материалом, представленным в главе 11, при Наследовании Заказного ObjectARX Класса, ” и главы 12, “ Происходящий от AcDbObject. ”

    Краткий обзор

    AutoCAD поддерживает многодокументную среду, и ObjectARX-приложения, выполняющиеся в пределах AutoCAD должны работать должным образом в среде MDI. Три принципа должны соблюстись для ObjectARX-приложения, чтобы обеспечить поддержку MDI:
    § приложение должен обслужить документированное - определенное состояние на стеке, в базе данных, или в структуре, которая может быть индексирована через соответствующий указатель документа.
    § Все документы должен быть блокирован, чтобы измениться. Основной документ блокировка обработана автоматически для AutoCAD, командует, ObjectARX команды, и функции AutoLISP. Немодальный диалог и код инструментальной панели, и любые команды, которые должны работать вне активного документа, должны вручную исполнить документ блокировка.
    § приложение должен обслужить{*поддержать*} отношения между документами и базами данных. Библиотека баз данных AutoCAD (AcDb) не сознает документы и MDI, и должна остаться так.
    Несколько архитектурных особенностей ObjectARX
    делают поддержку возможного MDI.
    Они включают отдельные контексты выполнения, образцы данных, документ блокировка, и классы управления документа. Следующие секции обсуждают эти темы{*разделы*} более подробно.

    Объектная модель программных компонентов Microsoft (COM) была первоначально разработана, чтобы поддержать связь и внедрение объектов (OLE); это также стало основанием ActiveX Автоматизации. Как стандарт на стадии становления для развития компонента Windows, COM имеет уместность вне OLE и ActiveX. Составляющая архитектура отделяет интерфейс от выполнения, позволяя приложения состоять из динамически связанных компонентов скорее чем отдельная двоичная выполнимая программа.
    Разработчики могут записывать программы, которые воспользуются преимуществом существующих компонентов COM, или они могут использовать COM, чтобы создать их собственные компоненты.
    ObjectARX-приложения могут быть разработаны как клиенты COM. Например, ObjectARX-приложение, которое должно связаться с другой программой, могло осуществлять COM, обращаются к той программе. В зависимости от интерфейсов COM, которые другое приложение обеспечивает, ObjectARX-приложение могло тогда обменивать информацию с прикладным обеспечением или даже драйвером.
    ObjectARX-приложение может также действовать как сервер автоматизации. Вы можете записывать обертки COM, чтобы выставить дополнительные элементы или заказные объекты ObjectARX. Новые API, шаблоны, классы, и поддержка для Microsoft Активная Библиотека Шаблонов (ATL) делают это проще чем когда-либо, чтобы добавить к AutoCAD ActiveX
    модель Автоматизации.


    ObjectDBX включает набор DLLS, который может использоваться, чтобы осуществить заказные объекты, содержащиеся в чертежном файле AutoCAD 2000, и осуществлять приложения, которые управляют DWG файлами без присутствия AutoCAD. Часть этой возможности была прежде представлена в DWG, отключенное изделие{*программа*}, но ObjectDBX SDK заменяет и идет вне DWG
    Отключенная технология,  обеспечивая поддержку, необходимую для интеллектуальных объектных систем. ObjectDBX SDK позволяет Вам создавать приложения главного компьютера не-автохама, которые могут читать и записывать DWG файлы.


    Программирование Диалогового окна возводит в степень две стадии:
    § Проектирование диалогового окна dialog box определены текстовыми файлами, написанными на языке контроля диалогов (DCL). Описание DCL диалогового окна определяет, как поле появляется и что это содержит. Для подробной информации, см. Часть III, “ Программируемая Ссылка Диалогового окна, ” в Руководстве Настройки AutoCAD.
    § Поддержка диалогового окна в ваших частях приложения диалогового окна определяют, как это ведет себя; однако, использование и поведение диалогового окна зависят от приложения, которое использует это.

    Кривые

    Кривые и поверхности в AcGe библиотеке параметрические. Кривая - результат отображения интервала реальной линии в 2D
    или 3D пространстве  и моделируется  использованием функции вычислителя с одним параметром, типа f (u). Точно так же поверхность - отображение 2D
    области  в пространство моделирования 3D
    использование функции вычислителя, основанной на двух параметрах например, f (u, v). Каждый 2D и 3D
    класс кривой  имеют getInterval () функция, которая возвращает параметрический интервал. Эта функция имеет две формы: первая возвращения интервал; вторая возвращает интервал также как точку начала и оконечную точку кривой.
    ОБРАТИТЕ ВНИМАНИЕ, является ли интервал неограничен в любом направлении, точках начала, и оконечные точки не имеют значения.

    Linetype Масштаб, указанный В Примитив

    Если значение масштаба linetype определено для примитива, текущее значение по умолчанию базы данных linetype значение масштаба игнорируется.
    Следующие функции позволяют Вам устанавливать и запрашивать масштаб linetype относительно примитива:
    Acad::ErrorStatus
    AcDbEntity::setLinetypeScale(double newVal);
    double
    AcDbEntity::linetypeScale() const;

    Linetype примитива

    Значение linetype указывает на вход таблицы идентификаторов, который определяет ряд точек и подчеркивает штриховой линией используемый для рисунка строк. Когда примитив - instantiated, его linetype установлен в NULL. Когда примитив добавлен к базе данных, если linetype не был определен для примитива, linetype установлен в поток базы данных linetype значение. Это значение по умолчанию сохранено в CELTYPE системной переменной.
    Linetype может быть определен по имени, строкой, или объектом ID AcDbLineTypeTableRecord в целевой базе данных примитива.
    Специальные linetype входы следующие:
    CONTINUOUS - Значение по умолчанию linetype, который автоматически создан в linetype таблице идентификаторов
    BYLAYER Linetype значение уровня примитива
    BYBLOCK Linetype значение примитива окружающий блочный поток определения блокирует ссылку{*справочники*}
    Если значение linetype определено для примитива, текущее значение по умолчанию базы данных linetype значение игнорируется.
    Следующие функции дают возможность Вам установить linetype для примитива, или по имени или объектом ID:
    virtual Acad::ErrorStatus
    AcDbEntity::setLinetype(const char* newVal);
    virtual Acad::ErrorStatus
    AcDbEntity::setLinetype(AcDbObjectId newVal);
    Эта функция возвращает название{*имя*} текущего примитива linetype:
    char* AcDbEntity::linetype() const;
    Эта функция возвращает объект ID для отчета{*записи*} таблицы идентификаторов определение linetype:
    AcDbObjectId AcDbEntity::linetypeId() const;

    Локализация и XMX Файлы

    С тех пор acdb.xmx оттранслирован для всех ограниченных версий AutoCAD, pretrans-lated XMX файлы теперь отправлены как часть ObjectDBX SDK, так что Вы можете создавать полностью ограниченное языком конечное изделие. Это позволит, Вы, чтобы создать несколько версий языка вашего приложения, или вашего приложения можете сделать запрос пользователя с выбором нескольких языков.
    Выбор языка будет ответственность вашего приложения. К тому концу, загрузка XMX файла находится в функции acdbValidateSetup ().
    Эта функция берет параметр LCID, чтобы определить выбор приложения языка. Функция будет пытаться загружать это XMX файл сначала,  используя AcDbHostApplicationServices:: findFile () метод и, если это терпит неудачу, смотря в каталоге, который содержит AcDb15.dll.
    Сигнатура для acdbValidateSetup ()
    Acad::ErrorStatus
    acdbValidateSetup( long lcid );
    Acdb.xmx файл теперь назван acdbLLL.xmx, где ЯЗЫК НИЗКОГО УРОВНЯ - сокращение локализации языка с тремя символами, которое может быть получено из LCID.
    Autodesk поддерживает, и в конечном счете отправит или иначе обеспечит, acdbLLL.xmx файлы на следующих языках.
    XMX файлы типа


    Language

    Language Abbreviation

    Language ID from LCID

    English (USA)

    ENU

    0409

    Chinese (Taiwan)

    CHT

    0404

    Chinese (Simplified)

    CHS

    0804

    Czech

    CSY

    0405

    French (Default)

    FRA

    040c

    German (Default)

    DEU

    0407

    Greek

    ELL

    0408

    Hungarian

    HUN

    040e

    Italian

    ITA

    0410

    Japanese

    JPN

    0411

    Korean

    KOR

    0412

    Polish

    PLK

    0415

    Portuguese (Brazilian)

    PTB

    0416

    Portuguese (Default)

    PTG

    0816

    Russian (Default)

    RUS

    0419

    Spanish (Default)

    ESP

    040a

    Как ObjectDBX разработчик, Вы должны делать две вещи создать ограниченный языком конечный продукт:
    § Вы должен отправить соответствующие acdbLLL.xmx файлы наряду с вашим изделием{*программой*}.
    § Вы должен сообщить ObjectDBX который acdbLLL.xmx файл загрузиться, пропуская соответствующий LCID к acdbValidateSetup ().
    Если LCID не соответствует одному из сокращений с тремя символами выше, или если соответствующий XMX файл не был отправлен, ваше приложение ObjectDBX будет не в состоянии загружаться должным образом.
    Если неспособно найти,  желательный acdb.xmx файл, acdbValidateSetup () будет пытаться загружать Английский язык как по умолчанию. Снова, это будет сначала использовать findFile (), и затем принимать тот же самый путь как AcDb15.dll. Если это находит Английский язык, но Английский язык не был,  требуемый язык, Acad:: eFileNotFound возвращен. Если функция неспособна найти любой acdb.xmx файл, это остановится с fatalError (), и ваше приложение не будет загружаться.

    Макрокоманда Объявления Класса

    Файл заголовка для заказного класса может использовать ACRX_DECLARE_MEMBERS (CLASS_NAME) макрокоманда ObjectARX, чтобы объявить desc(), cast(), и isA() функции.
    Эта макрокоманда используется в общем разделе объявления класса, следующим образом:
    class myClass : public AcRxObject
    {
                    public:
                    ACRX_DECLARE_MEMBERS(myClass);
                    ...
    };
    Для AsdkPoly, следующая строка расширяется до одиночной длинной строки программы.
    ACRX_DECLARE_MEMBERS (AsdkPoly);
    Когда переформатировано к множественным строкам для ясности, строка напоминает это:
    virtual AcRxClass* isA() const;
    static AcRxClass* gpDesc;
    static AcRxClass* desc();
    static AsdkPoly* cast(const AcRxObject* inPtr)
    {
                    return ((inPtr == 0) || ! inPtr->isKindOf(AsdkPoly::desc())) ? 0 : (AsdkPoly*)inPtr;
    };
    static void rxInit();
    Статический rxInit () функция и статический gpDesc указатель, объявленный этой макрокомандой используется, чтобы осуществить isA (), desc (), и cast() функции.

    Макрокоманды Выполнения Класса

    Чтобы осуществлять ваш заказной класс, используйте одну из этих трех макрокоманд в источнике file:
    · ACRX_NO_CONS_DEFINE_MEMBERS(CLASS_NAME, PARENT_CLASS)
     Использование для абстрактных классов и любых других классов, которые не должны быть instantiated.
    · ACRX_CONS_DEFINE_MEMBERS(CLASS_NAME, PARENT_CLASS, VERNO)
     Использование для переходных классов, которые могут быть instantiated, но не написано к файлу.
    · ACRX_DXF_DEFINE_MEMBERS(CLASS_NAME, PARENT_CLASS, DWG_VERSION,\
    MAINTENANCE_VERSION, PROXY_FLAGS, DXF_NAME, APP)
     Использование для классов, которые могут быть записаны в, или читать от, DWG и DXF файлы.
    Каждая из этих макрокоманд определяет следующее:
    · объект описателя Класса
    · функция инициализации Класса (см. “ Функция Инициализации Класса ” на странице 289)
    · desc () функция для этого класса
    · виртуальный isA () функция (унаследованный от AcRxObject) который этот заказной класс отменит
    Для AsdkPoly, следующая строка расширяется до очень длинной одиночной линии кода:
    ACRX_DXF_DEFINE_MEMBERS(AsdkPoly, AcDbCurve, AcDb::kDHL_CURRENT,\
    AcDb::kMReleaseCurrent, 0, POLYGON, /*MSG0*/"AutoCAD");
    Когда переформатировано к множественным строкам для ясности, строка напоминает это:
    AcRxClass* AsdkPoly::desc()
    {
                    if (AsdkPoly::gpDesc != 0)
                                   return AsdkPoly::gpDesc;
                    return AsdkPoly::gpDesc =
                                   (AcRxClass*)((AcRxDictionary*)acrxSysRegistry()->
                                                   at("ClassDictionary"))->at("AsdkPoly");

    }

    AcRxClass* AsdkPoly::isA() const

    {

                    return AsdkPoly::desc();

    }

    AcRxClass* AsdkPoly::gpDesc = 0;

    static AcRxObject * makeAsdkPoly()

    {

                    return new AsdkPoly();

    }

    void AsdkPoly::rxInit()

    {

                    if (AsdkPoly::gpDesc != 0)

                    return;

                    AsdkPoly::gpDesc = newAcRxClass("AsdkPoly",

                                                                   "AsdkCurve", AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent,

                                                                   0, &makeAsdkPoly, "POLYGON", "\"AutoCAD\"");

    };

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

    Если Вы хотите записать ваш собственный rxInit () функция, использовать ACRX_DEFINE_MEMBERS () макрокоманда отдельно, которая определяет desc (), cast (), и isA () для вашего класса, но не определяет rxInit () функция. Эта макрокоманда также не создает связанный объект AcRxClass, который является ответственностью rxInit () функция.

    Манипуляция наборами выборов

    Вы можете добавлять примитивы к набору выборов или удалять их из этого,  вызывая функции acedSSAdd () и acedSSDel (), которые являются подобными опциям Add и Remove, когда AutoCAD в интерактивном режиме запрашивает пользователя выбирать объекты или удалять объекты.
    ОБРАТИТЕ ВНИМАНИЕ На acedSSAdd () функция может также использоваться, чтобы создать новый набор выборов, как показано в следующем примере. Как с acedSSGet (), acedSSAdd () создает новый выбор, устанавливают только, если это возвращает RTNORM.
    Следующий типовой кодовый фрагмент создает набор выборов, который включает первые и последние примитивы в текущий рисунок.

    ads_name fname, lname; // Entity names
    ads_name ourset; // Selection set name
    // Get the first entity in the drawing.
    if (acdbEntNext(NULL, fname) != RTNORM) {
    acdbFail("No entities in drawing\n");
    return BAD;
    }
    // Create a selection set that contains the first entity.
    if (acedSSAdd(fname, NULL, ourset) != RTNORM) {
    acdbFail("Unable to create selection set\n");
    return BAD;
    }
    // Get the last entity in the drawing.
    if (acdbEntLast(lname) != RTNORM) {
    acdbFail("No entities in drawing\n");
    return BAD;
    }
    // Add the last entity to the same selection set.
    if (acedSSAdd(lname, ourset, ourset) != RTNORM) {
    acdbFail("Unable to add entity to selection set\n");
    return BAD;
    }
    Пример выполняется правильно, даже если имеется только один примитив в базе данных (когда и acdbEntNext () и acdbEntLast () устанавливают их параметры в то же самое имя примитива). Если acedSSAdd () пропускают имя примитива, который является уже в наборе выборов, это игнорирует запрос и не сообщает о ошибке.
    Поскольку пример также иллюстрирует, вторые и третьи параметры к acedSSAdd () можно пропускать как то же самое имя набора выбора. То есть если запрос успешен, набор выборов, названный обоими параметрами содержит дополнительного члена после acedSSAdd () возвращения (если указанный примитив не был уже в наборе выборов).

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

    AcedSSDel (fname, ourset);

    Если имеются больше чем один примитив в рисунке (то есть если fname и lname не равны), выбор устанавливает ourset, теперь содержит только lname, последний{*прошлый*} примитив в рисунке.

    Функция acedSSLength () возвращает число примитивов в наборе выборов, и acedSSMemb () испытания,является ли специфический примитив членом набора выборов. Наконец, функция acedSSName () возвращает имя специфического примитива в наборе выборов, используя индекс в набор (примитивы в наборе выборов пронумерованы от 0).

    ОБРАТИТЕ ВНИМАНИЕ, поскольку наборы выбора могут быть весьма большие, len параметр, возвращенный acedSSLength () должен быть объявлен как длинное целое число. Я параметр, используемый как индекс в звонит к acedSSName () должен также быть длинное целое число. (В этом контексте, стандартные компиляторы C правильно преобразуют простое целое число.)

    Следующий типовой код показывает несколько, вызывает к acedSSName ().

    ads_name sset, ent1, ent4, lastent;

    long ilast;

    // Create the selection set (by prompting the user).

    acedSSGet(NULL, NULL, NULL, NULL, sset);

    // Get the name of first entity in sset.

    if (acedSSName(sset, 0L, ent1) != RTNORM)

    return BAD;

    // Get the name of the fourth entity in sset.

    if (acedSSName(sset, 3L, ent4) != RTNORM) {

    acdbFail("Need to select at least four entities\n");

    return BAD;

    }

    // Find the index of the last entity in sset.

    if (acedSSLength(sset, &ilast) != RTNORM)

    return BAD;

    // Get the name of the last entity in sset.

    if (acedSSName(sset, ilast-1, lastent) != RTNORM)

    return BAD;

    Преобразование Наборов Выбора

    Функция acedXformSS () преобразовывает выбор, установленный,  применяя матрицу преобразования (типа ads_matrix) к примитивам в наборе. Это обеспечивает эффективную альтернативу к вызову ВРАЩАЮЩЕГОСЯ, МАСШТАБУ, ЗЕРКАЛУ, или командам ПЕРЕМЕЩЕНИЯ с acedCommand () (или acedCmd ()) или к изменению{*замене*} значений в базе данных с acdbEntMod (). Набор выборов может быть получен способом из обычных путей. Матрица должна делать однородное масштабирование. То есть элементы в векторе масштабирования S X S Y S Z должны весь быть равными; в матричном примечании, М. 00 М. 11 М. 22.


    Если вектор масштаба - не, униформа, acedXformSS () сообщает о ошибке.

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

    |  0.5   0.0  0.0  20.0  |

    |  0.0   0.5  0.0    5.0  |

    |  0.0   0.0  0.5    0.0  |

    |  0.0   0.0  0.0    1.0  |

    Применение{*обращение*} этой матрицы масштабирует примитивы половиной (который перемещает их к началу координат) и транслирует их местоположение (20.0,5.0).

    int rc, i, j;

    ads_point pt1, pt2;

    ads_matrix matrix;

    ads_name ssname;

    // Initialize pt1 and pt2 here.

    rc = acedSSGet("C", pt1, pt2, NULL, ssname);

    if (rc == RTNORM) {

    // Initialize to identity.

    ident_init(matrix);

    // Initialize scale factors.

    matrix[0][0] = matrix[1][1] = matrix[2][2] = 0.5;

    // Initialize translation vector.

    matrix[0][T] = 20.0;

    matrix[1][T] = 5.0;

    rc = acedXformSS(ssname, matrix);

    }

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

    Int scnf (ads_point запятая, ads_matrix mt)

    Это должно возвратить RTNORM, если это изменило матрицу, RTNONE, если это делало не, или RTERROR, если это обнаруживает ошибку.

    AcedDragGen () функция вызывает функцию scnf, каждый раз пользователь перемещает курсор. Scnf () функция устанавливает новое значение матрицы mt.

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

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

    int dragsample(usrpt, matrix)

    ads_point usrpt


    ads_matrix matrix;

    {

    ident_init(matrix); // Initialize to identity.

    // Initialize translation vector.

    matrix[0][T] = usrpt[X];

    matrix[1][T] = usrpt[Y];

    matrix[2][T] = usrpt[Z];

    return RTNORM; // Matrix was modified.

    }

    Наоборот, следующая версия dragsample () масштабирует набор выборов в текущем XY плане, но не перемещает это.

     int dragsample(usrpt, matrix)

    ads_point usrpt

    ads_matrix matrix;

    {

    ident_init(matrix); // Initialize to identity.

    matrix[0][0] = userpt[X];

    matrix[1][1] = userpt[Y];

    return RTNORM; // Matrix was modified.

    }

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

    int rc;

    ads_name ssname;

    ads_point return_pt;

    // Prompt the user for a general entity selection:

    if (acedSSGet(NULL, NULL, NULL, NULL, ssname) == RTNORM)

    rc = acedDragGen(ssname, // The new entities

    "Scale the selected objects by dragging", // Prompt

    0, // Display normal cursor (crosshairs)

    dragsample, // Pointer to the transform function

    return_pt); // Set to the specified location

    Более сложные преобразования могут вращать примитивы, комбинировать{*объединять*} преобразования (как в acedXformSS () пример), и т.д.

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

    void xformcompose(ads_matrix xf1, ads_matrix xf2,

    ads_matrix resmat)

    {

    int i, j, k;

    ads_real sum;

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

    for (j=0; j<=3; j++) {

    sum = 0.0;

    for (k=0; k<3; k++) {

    sum += xf1[i,k] * xf2[k,j];

    }

    resmat[i,j] = sum;

    }

    }

    }

    Матрицы Преобразования

    Функции acedDragGen (), acedGrVecs (), acedNEntSelP (), и acedXformSS () умножают входные векторы на матрицу преобразования, определенную как 4x4 массив реальных значений.
    typedef ads_real ads_matrix [4] [4];
    Первые три столбца матрицы определяют масштабирование и вращение. Четвертый столбец матрицы - вектор сдвига. ObjectARX определяет символ T, чтобы представить координату этого вектора, следующим образом:
     #define T 3
    Матрица может быть выражена следующим образом:

    М. 00
     М. 01
    М. 02
     М. 03
    М. 10
    М. 11
     М. 12
     М. 13
    М. 20
     М. 21
     М. 22
    М. 23
    0.0
    0.0
    0.0
    1.0

    Следующая функция инициализирует единичную матрицу.
    void ident_init(ads_matrix id)
    {
    int i, j;
    for (i=0; i<=3; i++)
    for (j=0; j<=3; j++)
    id[i][j] = 0.0;
    for (i=0; i<=3; i++)
    id[i][i] = 1.0;
    }
    Функции, которые передают параметры типа ads_matrix, обращаются с точкой как вектор столбца измерения 4. Точка выражена в гомогенных координатах, где четвертый элемент вектора точки - коэффициент масштаба, который обычно устанавливается в 1.0. Конечная{*заключительная*} строка матрицы имеет номинальное значение [0,0,0,1]; это игнорируется функциями тот проход ads_matrix параметры. В этом случае, следующие матричные результаты умножения от приложения преобразования к точке:

    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 (1.0)
    Y ' = М. 10 X + М. 11 Y + М. 12 Z + М. 13 (1.0)
    Z ' = М. 20 X + М. 21 Y + М. 22 Z + М. 23 (1.0)
    Как этот показ уравнений, коэффициент масштаба и последняя строка матрицы не имеет никакой эффект и игнорируется. Это известно как афинное преобразование.

    ПРИМЕЧАНИЕ, чтобы преобразовать вектор скорее чем точка, не добавьте в векторе сдвига М3 М13 М23 (от четвертого столбца матрицы преобразования).

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

    void xformpt(xform, pt, newpt)

    ads_matrix xform;

    ads_point pt, newpt;

    {

    int i, j;

    newpt[X] = newpt[Y] = newpt[Z] = 0.0;

    for (i=X; i<=Z; i++) {

    for (j=X; j<=Z; j++)

    newpt[i] += xform[i][j] * pt[j];

    // Add the translation vector.

    newpt[i] += xform[i][T];

    }

    }

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

    ( Значения в ads_matrix - фактически ads_real, но им показывают здесь как целые числа для удобочитаемости и соответствовать математическому соглашению.)

    1

    0

    0

    0

    1

    0

    0

    TX

    SX

    0

    0

    0

    cos

    -sin

    0

    0

    0

    1

    0

    0

    0

    1

    0

    TY

    0

    SY

    0

    0

    sin

    cos

    0

    0

    0

    0

    1

    0

    0

    0

    1

    TZ

    0

    0

    SZ

    0

    0

    0

    1

    0

    0

    0

    0

    1

    0

    0

    0

    1

    0

    0

    0

    1

    0

    0

    0

    1

    Translation                               scaling                      2D rotation (in the XY plane)

    AcedXformSS () функция — в отличие от acedDragGen(), acedGrVecs(), или acedNEntSelP() функции — требует, чтобы  матрица делала однородное масштабирование. То есть в матрице преобразования, которую Вы проходите к acedXformSS (), элементы в векторе масштабирования S X S Y S Z, должны весь быть равными; в матричном примечании, М. 00 = М. 11 = М. 22. Трехмерное вращение - слегка различный случай, как показано в следующем рисунке:

    cos

    -sin

    0

    0

    1

    0

    0

    0

    cos

    0

    sin

    0

    sin

    cos

    0

    0

    0

    cos

    -sin

    0

    0

    1

    0

    0

    0

    0

    1

    0

    0

    sin

    cos

    0

    -sin

    0

    cos

    0

    0

    0

    0

    1

    0

    0

    0

    1

    0

    0

    0

    1

    <


    rotation in the XY plane               rotation in the YZ plane               rotation in the XY plane

    Для однородных вращений, 3x3 субматрица, разграниченная [0,0] и [2,2] - orthonormal. То есть каждая строка - вектор модуля и перпендикулярна к другим строкам; скалярное (точечное) программа двух строк нулевое. Столбцы - также векторы модуля, которые являются перпендикулярными к друг другу. Программа orthonormal

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

    Сложные преобразования могут быть выполнены,  объединяя{*комбинируя*} (или составляя) значения нетождества в единственной{*отдельной*} матрице.

    ОБРАТИТЕ ВНИМАНИЕ На acedTablet () функция использует 3x3 матрицу, чтобы преобразовать 2-ые точки. AcedNEntSel () функция использует 4x3 матрицу преобразования, которая является подобной 4x4 матрица преобразования, но это обращается с точкой как строка.

    MDI-РАСШИРЕННЫЙ Уровень

    Эти дополнительные шаги будут заставить ваше приложение интегрировать полностью с МНОГОДОКУМЕНТАЛЬНЫМ ИНТЕРФЕЙСОМ.
    § Рассматривают перемещение вашего AcEditorReactor:: commandXxx () и AcEditorReactor:: LispXxx () повторные вызовы, чтобы работать вместо этого от AcDocMananagerReactor::documentLockModeWillChange () и AcDocMananagerReactor::documentLockModeChanged () уведомления. Тогда они объяснят прикладные операции контекста выполнения, которые были предварительно трудны обнаружить ObjectARX-приложениями.
  • Избегают использовать acedCommand (). Используйте AcApDocManager:: setStringToExecute () вместо этого, потому что это имеет параметр документа.

  • Избегают использовать kLoadDwg и kUnloadDwg случаи, и использовать documentToBeCreated () и documentToBeDestroyed () реакторы вместо этого.

  • Поддерживают документированную - независимую особенность базы данных. Для большего количества информации, см. " Документированные - независимые Базы данных " на странице 439.

  • команды много-документа Поддержки. Для подробной информации, см. " Команды Много-документа " на странице 432.

  • Поддерживают все события, которые происходят в пределах прикладного контекста выполнения. Для подробной информации, см. " Прикладной Контекст Выполнения " на странице 436.


  • MDI-СПОСОБНЫЙ Уровень

    Достижение этого уровня согласия вовлекает создание вашей работы кода так эффективно и естественно в режиме MDI, как это делает (или делало) в режиме SDI.
    §
    переключение документа поддержки.
    Секции Кода, включающие AcEd-зарегистрированные команды, которые вызваны непосредственно от тех конструкций,  вероятно будет делать паузу для ввода пользователя, и более вероятны восприимчивы к коррупции, когда множественные сессии сделаются. Наиболее общий случай должен ввести команду в один документ, подсказка для ввода пользователя, затем переключать документы и вводить ту же самую команду в различный документ. Пока Вы поддерживаете жизненную информацию относительно основания " в открытый документ ", ваше приложение должно функционировать должным образом. Иначе, ваш код должен отключить переключение документа.
    § поддерживают хорошую работу.
    Когда это становится временем, чтобы смотреть на выполнение{*работу*}, много разыменования указателя резидента динамическая к тому, что было прежде статические адреса, может трясина вниз выполнения{*работы*} программы. В этом случае, альтернатива была бы должна обслужить{*поддержать*} статический буфер памяти элементов текущего документа, который будет просмотрен в от и выписан к документированным - определенным элементам динамической памяти.

    MDI-ЗНАЯ Уровень

    Этот уровень совместимости обеспечивает минимальные требования для ObjectARX-приложения, чтобы функционировать в среде MDI без неудачи.
    ObjectARX-приложение должно встретить{*выполнить*} требования этого уровня совместимости перед способностью законно установить SDI
    переменную системы в 0.
    Следующий список суммирует минимальные требования.
    N Приложения не может сохранять данные " в документ " в глобальных или статических переменных.
    N, если команда выполнена от прикладного контекста, это должно обеспечить явный документ блокировка.
    N Автошепелявящиеся - зарегистрированные команды должен быть подготовлен, чтобы действовать в пределах множественных государств AutoLISP.
    N Приложения должен регистрировать себя как MDI-ЗНАЮЩИЕ в течение их AcRx:: kInitAppMsg обработчик в acrxEntryPoint ().
    Каждое требование описано подробно в следующих секциях.

    Менеджер Размещения

    Вы можете управлять объектами AcDbLayout,  используя AcApLayoutManager класс.
    AcApLayoutManager класс позволяет Вам
    § Создают размещения
    § Удаляют размещения
    § Переименовывают размещения
    § Копия и размещения аналога
    § Набор текущее размещение
    § Находят специфическое размещение
    § Набор графические характеристики размещения
    Имеется один образец менеджера размещения в приложение. Менеджер размещения всегда работает на текущем размещении.

    Менеджер Свойства объекта API

    Менеджер Свойства объекта (OPM) - инструмент, который позволяет пользователям рассматривать и изменять свойства примитивов и объектов легко. См. Руководство программиста AutoCAD для подробной информации относительно особенностей OPM и интерфейса пользователя.
    OPM поддерживает два вида свойств. Первый - свойства, которые определены для объекта статически во времени компиляции, названных статических свойствах.
    Динамические свойства, которые являются свойствами, которые могут быть добавлены и конфигурирован во время выполнения, также поддержаны. Для статических свойств, ObjectARX-приложения могут обеспечивать COM классами “обертки” для их заказных объектов. OPM будет использовать эти классы, чтобы определить, который статические свойства являются ли доступным для того объекта и как к “flavorize” те свойства для дисплея (типа, свойство требуют заказного поля со списком в OPM, или должны поднять диалог для редактирования свойства?). Для динамических свойств, ObjectARX, VB, или приложений VBA может создавать “ свойство plug-ins
    ” использование OPM
    Динамического API Свойств, чтобы конфигурировать и управлять свойствами для любого аборигена или класса пользователя во время выполнения.

    Менеджер точки ввода

    ObjectARX обеспечивает  менеджера ввода точки классом, AcEdInputPointManager.
    Один входной менеджер точки инициализирован для каждого активного документа в AutoCAD.
    Следующая функция возвращает входного менеджера точки для документа:
    virtual AcEdInputPointManager *
    AcApDocument::inputPointManager() const;
    Входной менеджер точки регистрирует и вычеркивает из списка входные фильтры точки, входные мониторы точки, и  реакторы контекста ввода. Входной менеджер точки также позволяет и отключает сгенерированную системой графику курсора, так, чтобы заказная графика курсора могла рисовать.
    AcEdInputPointManager обеспечивает функцию, disableSystemCursorGraphics(), который отключает курсор системы.
    ObjectARX поддерживает индекс,  вызывает, чтобы отключить курсор системы для каждого документа, так, если ваше приложение вызывает disableSystemCursorGraphics() множественные времена, это должно вызвать enableSystemCursorGraphics() то же самое число раз, чтобы восстановить курсор системы.
    ПРЕДУПРЕЖДЕНИЕ! Отключение графики курсора системы должно быть сделано экономно, обычно только, когда определенная приложением команда запрашивает ввод пользователя.
    Вы должны обеспечить заказную графику курсора, если Вы отключаете графику курсора системы.
    Функция disableSystemCursorGraphics () отключает курсор системы только, когда входной монитор точки или фильтр обеспечивают его собственный курсор. Это означает, что при нормальных условиях (принудительный выбор примитива выключен), курсор системы заблокирован только в течение приобретения точки и выбора примитива.
    Когда принудительный выбор примитива включен, курсор системы полностью заблокирован, даже если не имеется никакой активной команды.
    Входной менеджер точки также позволяет принудительный выбор примитива, который является способностью проследить то, что находится под курсором в течение статического состояния команды.
    Принудительный выбор примитива можно позволять при следующих условиях:
    § в течение входного приобретения точки без активного режима объектной привязки
    § в течение выбора отдельного примитива точки
    § в течение неподвижности команды
    Наконец, входной менеджер точки содержит функцию, mouseHasMoved(), те входные фильтры точки, и мониторы могут вызывать, чтобы определить, имеется ли другая задержка события цифрового преобразователя. Если имеется задержка события цифрового преобразователя, фильтр, или монитор должен возвратиться от его повторного вызова как можно скорее, без того, чтобы делать любые дальнейшие вычисления, избегать курсора задержки.

    Менеджер транзакции

    Операционный менеджер - глобальный менеджер объект, подобный редактору, который отвечает за транзакции поддержания. Это - образец AcTransactionManager и поддержан в системном реестре системы. Вы можете получить это от системного реестра системы, используя макрокоманду actrTransactionManager, который расширяется до
    #define actrTransactionManager \
    AcTransactionManager::cast ( acrxSysRegistry()->at(AC_TRANSACTION_MANAGER_OBJ) )
    Операционный менеджер должен использоваться, чтобы запустить, заканчивать, или прервать транзакции.
    Это может также обеспечивать информацию типа числа активных транзакций в любой момент (см. следующую секцию, при Вложении транзакций ”) и список всех объектов, чей указатели были получены во всех транзакциях. Операционный менеджер поддерживает список реакторов, чтобы уведомить клиентов относительно событий типа начала, конца, или аварийного прекращения работы транзакции.
    В дополнение к этим организаторским возможностям, операционный менеджер может также использоваться, чтобы получить указатели от объекта IDs. Когда это сделано, объект связан с высшей (самой современной) транзакцией. Операционный менеджер может также использоваться, чтобы стоять в очереди все объекты во всех транзакциях для графической модификации и сбрасывать на диск очередь.
    Операционный менеджер объект создан и управляется системой. Вы не должны удалить это.

    Метки для Диалоговых окон и Неперекрывающих расположений

    Adsdlg.h файл определяет два типа метки:
    §
    ads_hdlg идентифицирует диалоговые окна. Ads_new_dialog () функция назначает новое диалоговое окно,  метка ads_hdlg для идентификации диалогового окна в наиболее последующий вызывает к функциям PDB, пока ads_done_dialog () не вызван.
    § ads_htile идентифицирует отобранное неперекрывающее расположение в пределах функций повторного вызова.
    Если ads_new_dialog () сбои, это устанавливает метку в NULL или BAD_DIALOG.

    Метки примитива и их использования

    AcdbHandEnt () функция отыскивает имя примитива с определенной меткой. Подобно именам примитива, метки уникальны в пределах рисунка. В отличие от имен примитива, метка примитива постоянна повсюду его жизни. ObjectARX приложения, которые управляют определенной базой данных, могут использовать acdbHandEnt () чтобы получить текущее имя примитива, который они должны использовать.
    Следующий типовой кодовый фрагмент использует acdbHandEnt () чтобы получить имя примитива и распечатывать это.
    char handle[17];
    ads_name e1;
    strcpy(handle, "5a2");
    if (acdbHandEnt(handle, e1) != RTNORM)
    acdbFail("No entity with that handle exists\n");
    else
    acutPrintf("%ld", e1[0]);
    В одном сеансе редактирования частности, этот код мог бы распечатывать 60004722. В другом сеансе редактирования с тем же самым рисунком, это могло бы печатать полностью отличный номер. Но в обоих случаях, код обращается к тому же самому примитиву.
    AcdbHandEnt () функция имеет дополнительное использование: примитивы, удаленные из базы данных (с acdbEntDel ()) не очищены, пока Вы не оставляете текущий рисунок (выходя Из AutoCAD или переключая к другому рисунку). Это означает, что acdbHandEnt () может возвращать названия{*имена*} удаленных примитивов, которые могут тогда быть восстановлены к рисунку вторым запросом к acdbEntDel ().
    Примитивы в рисунках перекрестно ссылались с внешних ССЫЛОК, присоединяются не фактически часть текущего рисунка; их метки неизменны, и нельзя обращаться acdbHandEnt (). Однако, когда рисунки объединены посредством ВСТАВКИ, ВСТАВЬТЕ *,  XREF Связывает (XBIND), или частичный DXFIN, метки примитивов в рисунке прихода потеряны, и входящие примитивы назначены новые значения маркера{*дескриптора*} гарантировать, что каждый маркер{*дескриптор*} в рисунке оригинала остается уникальным.
    ОБРАТИТЕ ВНИМАНИЕ, что расширенные данные могут включать метки примитива, чтобы сохранить относительные структуры в рисунке. В некоторых обстоятельствах, эти метки требуют трансляции или обслуживания. См. “ Использование метки в Расширенных Данных ” на странице 240.

    MFC и Немодальные Диалоговые окна

    Так как AutoCAD пытается забирать центр от всех его дочерних окон, немодальные диалоги имеют специальное требование. Равномерно, немодальный диалог получит сообщение окна WM_ACAD_KEEPFOCUS, которое определено в adscodes.h как 1001. Когда ваш диалог получает это сообщение, это возвратило бы ИСТИНУ, если это сохранило центр. Если ответ на это сообщение ЛОЖНЫЙ (который является также значением по умолчанию), то ваше диалоговое окно будет терять центр, как только пользователь перемещает указатель от окна поля диалога.
    Вы можете делать это с картой сообщения поля диалога, и ON_MESSAGE () объявление типа
    BEGIN_MESSAGE_MAP (HelloDlg, CDialog)
    ON_COMMAND (IDCLOSE, OnClose)
    ON_COMMAND (IDC_DRAW_CIRCLE, OnDrawCircle)
    ON_MESSAGE (WM_ACAD_KEEPFOCUS, onAcadKeepFocus)
    END_MESSAGE_MAP ()
    В этом примере, диалоговый класс приложения - HelloDlg, который получен из CDialog. Когда Вы добавляете этот вход в карту сообщения, Вы должны также записать функцию обработчика для сообщения. Предположите, что Вы написали функцию, вызвал keepTheFocus(), который возвращает ИСТИНУ, если ваш диалог хочет сохранить фокус ввода и ЛОЖЬ, если диалог желает выдавать фокус AutoCAD. Обработчик сообщения примера обеспечивается здесь:
    afx_msg LONG HelloDlg::onAcadKeepFocus(UINT, LONG)
    {
                    return keepTheFocus() ? TRUE : FALSE;
    }

    Мягкие Указатели

    Мягкий указатель - просто указатель на объект. Это не защищает упомянутый объект от чистки.
    Примеры мягких ссылок указателя
    § Xdata ссылки - мягкие указатели.
    § Постоянные реакторы - мягкие указатели.
    Если Вы используете мягкий указатель, чтобы обратиться{*отнестись*} к объекту, Вы должны проверить{*отметить*}, чтобы объект все еще существовал прежде, чем Вы открываете это.

    Много-документные команды

    Команда много-документа позволяет пользователям переключать документы при отобранных подсказках пользователя, в то время как команда остается в контроле. Способность иметь единственную команду остается активной поперек документов,  очень сложен. В точке выполнения, когда пользователь выбрал, другой документ, чтобы переключить к, все документы голосует для ввода. Они поэтому имеют потенциально запутанные установленные состояния командного процессора, включая возможно вложенные команды, выражения AutoLISP, сценарии, активные, и все в произвольном порядке вложения.
    Не может легко определять, уже не говоря о прививают, подходящие элементы одного состояния в другой без главного усилия. Вместо этого, лучшая стратегия - для приложения, чтобы сохранить контроль поперек указанных пользователем выключателей документа, даже если приложение должно быть осуществлено как различные команды в различных окнах. Тогда, все прикладные потребности - механизм к цепным отдельным командам, выполняющимся в различных документах, и контроле, которые командуют, чтобы начаться при изменении{*замене*} документов.
    Чтобы синхронизировать действия множественных команд, осуществьте реактор, который перегружает следующие AcApDocManager реакторные функции:
    virtual void
    documentActivated( AcApDocument* pActivatedDoc );
    virtual void
    documentToBeDeactivated( AcApDocument* pDeActivatedDoc );
    DocumentToBeActivated() реакторная функция может также использоваться, но это происходит прежде, чем документ активизирован. Контекст документа не был установлен в этом случае.
    Эти повторные вызовы вызваны всякий раз, когда пользователь нажимает на различный документ, чтобы активизировать это. Реакторы должны только использоваться на AcApDocManager, когда в начальной команде как раз перед запросом ввода пользователя, в точке, когда переключение документа должно быть поддержано. Реактор должен быть удален, когда любой или все такие подсказки закончены или отменены. От повторного вызова, вызовите:

    virtual Acad::ErrorStatus

    sendStringToExecute(

    AcApDocument* pAcTargetDocument,

    const char * pszExecute,

    bool bActivate = true,

    bool bWrapUpInactiveDoc = false) = 0;

    Эта функция стоит в очереди строка, которую нужно интерпретировать следующий раз,  указанный документ активизирован. Строка должна типично быть обращение команды (мы назовем это вторичной командой), но можем также быть выражение AutoLISP, фрагмент команды, или лексема меню. Строковый предел - 296 байтов, так что более длинные последовательности должны быть осуществлены как команда SCRIPT, выполняющая временный сценарий, или как выражение AutoLISP, чтобы загружать и выполнить программу AutoLISP. Новый документ будет блокирован согласно уровню блокировок новой команды как определено в течение его регистрации.

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

    ОБРАТИТЕ ВНИМАНИЕ, поскольку эта методика вовлекает запрос от documentActivated () метод, Вы должны передать kFalse в bActivate параметр, чтобы избежать ошибок или бесконечных циклов.

    Также, чтобы управлять потоком контроля поперек документов, этот повторный вызов должен поддержать любой переход, заявляют прикладные потребности. Например, неповторно используемый вариант мог помнить оригинал документа, и флажок для каждого документа, чтобы указать,является ли это уже активным, и поэтому не должны вызвать sendStringToExecute ().

    Когда команда много-документа заканчивает, приложение управления должно убедиться, что  команда не оставила никакие ждущие обработки состояния команды в предыдущих документах. Приложение может делать это,  посылая ESC или ВВОДИТЬ в документы, которые это пересекло через, используя bWrapUpInactiveDoc параметр sendStringToExecute (). Если это не сделано, документы могут быть оставлены в не-статическом состоянии.

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


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

    Помните ту ОТМЕНУ, выполняет отдельно в каждом документе при проектировании этих конструкций.

    ОБРАТИТЕ ВНИМАНИЕ, что  "нормальная" acedSSGet() не жизнеспособна, потому что это может запрашивать множественные времена, таким образом не возвращая любой набор выборов в продвижении. Вместо этого, acedEntSel() используется, потому что это или возвращает примитив, или RTNONE, означая пользователя действительно сделан, или RTCAN, который может быть или реальная отмена или "перемещенный в другой документ" сигнал. Установите местный "done" флажок, исполните действие, затем стойте в очереди ESC к каждому другому активному документу так, чтобы команда была закончена в том документе следующий раз,  пользователь идет к щелчку в это.

    Модификация Системного реестра при Инсталляции Приложения ObjectArx

    AutoCAD использует Windows NT (или Windows 95) системный реестр, чтобы расположить Приложения ObjectArx для загрузки запроса. Часть раздела AutoCAD системного реестра используется для информации относительно местоположения информации системного реестра ObjectARX appli-cations'.
    Инсталляционная программа для Приложения ObjectArx должна создать определенные клавиши{*ключи*} и значения в системном реестре, которые требуются для загрузки запроса. Некоторые из требуемых клавиш{*ключей*} и значений должны быть созданы в разделе AutoCAD системного реестра, и другие должны быть созданы в разделе приложения ObjectARX системного реестра.
    Если Приложение ObjectArx разработано{*предназначено*}, чтобы работать с больше чем одной версией AutoCAD (то есть различных версий языка или связанных изделий{*программ*}, типа Карты AutoCAD), инсталляционная программа должна прибавить соответствующую информацию к разделу системного реестра для каждой версии AutoCAD.
    Инсталляционный процесс для Приложений ObjectArx должен поэтому включить:
    · Проверка, что разделы системного реестра для соответствующей версии AutoCAD существуют. (Если раздел AutoCAD системного реестра не существует, пользователь должен быть предупрежден, что совместимая версия AutoCAD не была установлена, и инсталляция должна быть прервана.)
    · Создание определенного набора клавиш{*ключей*} и значений для приложения в пределах раздела (ов) системного реестра для соответствующей версии (й) AutoCAD.
    · Создание главной клавиши{*ключа*} для приложения непосредственно, и совокупности той клавиши{*ключа*} с другим набором определенных клавиш{*ключей*} и значений. См. \objectarx\samples\polysamp\demandload каталог ObjectARX
    SDK для информации относительно того, как системный системный реестр изменяется для запроса, загружающего типовую программу polysamp.
    Следующий два раздела описывают, как инсталляционная программа приложения должна создать системную информацию системного реестра, требуемую для загрузки запроса. Типовая инсталляционная программа включена в \objectarx\utils каталог ObjectARX SDK.

    Монопольное использование Базы данных Объектов

    Объект, который неявно принадлежит базе данных скорее чем другой объект базы данных,  называется корневым объектом. База данных содержит десять корневых объектов: эти девять таблиц идентификаторов и названный объектный словарь. Все файловые операции начинаются,  регистрируя из корневых объектов базы данных. См. “ Запись в файл Объекта ” на странице 95.
    За исключением корневых объектов, каждый объект в базе данных должен иметь владельца, и данный объект может иметь только одного владельца. База данных - дерево, созданное этой иерархией находящихся в собственности объектов. Следующий запрос прибавляет объект к базе данных и назначает ИДЕНТИФИКАТОР на это, но объект еще не имеет владельца: db- > addAcDbObject (...); Обычно, Вы прибавите объект к его владельцу, использующему функцию элемента, которая одновременно прибавляет это к базе данных, типа AcDbBlockTableRecord:: appendAcDbEntity () функция, которая исполняет обеих задачи сразу.
    Подключения{*связи*} монопольного использования AutoCAD следующие:
  • блочная таблица делает запись собственных объектов.

  • Каждая таблица идентификаторов имеет специфический тип отчета{*записи*} таблицы идентификаторов.

  • объект AcDbDictionary может иметь любой объект AcDbObject.

  • объект Any AcDbObject может иметь словарь расширения{*продления*}; объект имеет его словарь расширения{*продления*}.

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

    Монопольное использование Примитива

    Примитивы в базе данных обычно принадлежат AcDbBlockTableRecord. Блочная таблица в недавно созданной базе данных имеет три предопределенных отчета{*записи*}, *MODEL_SPACE, *PAPER_SPACE, и *PAPER_SPACE0, которые представляют образцовое пространство{*пробел*} и два предопределенных бумажных пространственных размещения. Дополнительные записи добавлены всякий раз, когда пользователь создает новые блоки (блочные записи), типично,  издавая БЛОК, ШТРИХОВКУ, или команду DIMENSION.
    Структура монопольного использования для примитивов базы данных следующие:
    Монопольное использование Примитива
    Монопольное использование Примитива
    Примитивы AutoCAD 12
    Следующие примитивы были включены в Выпуск AutoCAD 12 и объявлены в dbents.h файле. Вы не можете безопасно получать новые классы из следующего
    Выпустите 12 примитивов:
    N AcDb2dPolyline
    N AcDb3dPolyline
    N AcDbPolygonMesh
    N AcDbPolyFaceMesh
    N AcDbSequenceEnd
    N AcDbBlockBegin
    N AcDbBlockEnd
    N AcDbVertex
    N AcDbFaceRecord
    N AcDb2dVertex
    N AcDb3dPolylineVertex
    N AcDbPolygonMeshVertex
    N AcDbPolyFaceMeshVertex
    N AcDbMInsertBlock

    Набор Выборов и имена Примитива

    Большинство функций ObjectARX, которые обрабатывают наборы выбора и примитивы, идентифицирует{*выделяет*} набор или примитив его именем, которое является парой longs, назначенного и поддерживаемого AutoCAD. В ObjectARX, названия{*имена*} наборов выбора и примитивов имеют соответствующий тип ads_name.
    Прежде, чем это может управлять набором выборов или примитивом, приложение ObjectARX должно получить текущее имя набора или примитива,  вызывая одну из библиотечных функций, который возвращает набор выборов или имя примитива.
    ОБРАТИТЕ ВНИМАНИЕ на набор Выборов, и названия{*имена*} примитива энергозависимы; они применяются только, в то время как Вы работаете над рисунком к AutoCAD, и они потеряны при выходе от AutoCAD или переключения к другому рисунку.
    Для наборов выбора, которые также применяются только к текущему сеансу, энергозависимость названий{*имен*} не излагает никакую проблему, но для примитивов, которые сохранены в базе данных рисунка, это делает. Приложение, которое должно обратиться{*отнестись*} в разное время к тем же самым примитивам в том же самом рисунке (или рисунки), может использовать маркеры{*дескрипторы*} примитива, описанные в “ Маркеры{*дескрипторы*} Примитива и Их Использования ” на странице 216.

    Наследование Нового Класса от AcEdJig

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

    Наследование Заказных примитивов

    AcDbEntity - базовый класс для всех объектов базы данных, имеющих графическое представление.
    AcDbEntity получен из AcDbObject. Создание заказного объекта возводит в степень следующие шаги.
    Создавать заказной объект
    1 Получают класс пользователя из AcDbEntity.
    2 Перегружаемый все необходимые функции AcDbObject. См. главу 12, “ Происходящий от AcDbObject. ”
    3 Перегрузят требуемые функции AcDbEntity. Это будет обсуждено в следующих разделах.
    4 Перегрузят другие функции как необходимо, чтобы поддержать ваши заказные функциональные возможности.
    5, если Вы хотите поддержать,  команда MATCHPROP, осуществляет AcDbMatchProperties как расширение{*продление*} протокола.
    6, если Вы хотите создать заказной, перемещаетесь{*перетаскиваете*} последовательность для вашего объекта, осуществляете вашу собственную версию AcEdJig.
    Следующие разделы обсуждают эти темы{*разделы*} более подробно.

    Недавно созданные объекты и транзакции

    Имеются два способа иметь дело недавно с созданными объектами в операционном контексте управления.
    Рекомендуемый подход состоит в том, чтобы закрыть () объект после добавления этого к базе данных или соответствующему контейнеру и сохранять ИДЕНТИФИКАТОР, который возвращен Вам. Право после закрытия объекта, который передает{*совершает*} это базе данных, Вы может использовать getObject () функция, чтобы получить новый указатель для ваших операций.
    Даже если Вы вызываете близко () на объекте после добавления этого к базе данных, ее создание будет уничтожено, если содержащая транзакция прервана. См. “ Смешивание Модели Транзакции с Открытым и Близким Механизмом ” на странице 455.
    Дополнительный подход состоит в том, чтобы добавить ваш недавно созданный, в оперативной памяти объект к базе данных или на соответствующий контейнер, который в свою очередь добавит это к базе данных.
    Тогда добавьте это к самой современной транзакции, использующей AcTransactionManager::addNewlyCreatedDBRObject () или AcTransaction:: addNewlyCreatedDBRObject. Теперь, когда это связано с транзакцией, это будет совершено{*передано*} или несоздан в зависимости от того, заканчиваются ли транзакции успешно или аварийное прекращение работы.

    Немедленная и задержанная передача событий

    Для AcDbObjectReactor события уведомления могут или происходить немедленно или быть задержано на время. Используйте задержку, когда объект закрыт, если Вы работаете на основании " в объект ", или конец наиболее удаленной сделки, если Вы используете операционную модель. Следующие события посылают немедленное уведомление:
    cancelled()
                    Уведомление послано, когда AcDbObject::cancelled()
    вызван.
    openedForModify()
    Уведомление послано перед первым вызовом функции модификации, прежде, чем состояние объекта изменено.
    copied()
    Уведомление послано, когда объект скопирован.
    goodbye()
    Уведомление послано, когда объект собирается быть удаленным из памяти.
    Немедленные уведомления вызваны в то же самое время как соответствующее событие. Например, когда assertWriteEnabled () вызван первый раз на объекте, openedForModify () уведомление немедленно послано всем реакторам на том объекте.
    Следующие события посланы с задержкой:
    n modified()
    n subObjModified()
    n erased()
    n modifyUndone()
    n modifiedXData()
    n unappended()
    n reappended()
    n graphicsModified()
    modified() уведомление о AcDbObjectReactor - пример передавать-разового уведомления. Предположим, что объект открыт, и функция модификации - обратился к этому. Функция модификации вызывает assertWriteEnabled() и все реакторы получают openedForModify() реакция. Последующие функции модификации на объекте не приводят к любому дальнейшему уведомлению. Когда объект наконец закрыт, modified() уведомление послано. Однако, если новичок хотел называть cancel()
    на объекте вместо cancelled(), cancel()
    уведомление будет послано вместо cancelled() уведомление.
    Когда Вы получаете задержанное уведомление типа modified(), один из параметров - указатель на объект. В это время объект находится в состоянии только для чтения. Вы не способны изменить это до конца совершающегося процесса.
    При попытке изменять объект прежде, чем совершающийся процесс закончен, есть причины AutoCAD, чтобы прерваться с сообщением об ошибках eWasNotOpenForWrite или eInProcessOfCommitting.

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

     AcDbObjectReactor::objectClosed(AcDbObjectId ObjId);

     AcTransactionReactor::transactionEnded(int NumActiveAndSuccessful);

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

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

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

     AcTransactionReactor::endCalledOnOutermostTransaction()

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

    Вместо этого, ждите, пока целая сделка не закончена прежде, чем Вы исполняете любые операции на этих объектах.

    Номер цвета Базы данных

    Если цвет не определен для объекта, текущего номера цвета базы данных, сохранен в CECOLOR системной переменной, используется. Следующий набор функций и восстанавливает{*отыскивает*} текущий номер цвета в базе данных:
    Acad::ErrorStatus
    AcDbDatabase::setCecolor(const AcCmColor& color);
    AcCmColor AcDbDatabase::cecolor() const;

    Объектная Привязка

    AcedOsnap () функция находит точку,  используя один из Режимов объектной привязки AutoCAD. Поспешные режимы определены в строковом параметре.
    В следующем примере, запрос к acedOsnap () ищет midpoint линии около pt1.
    acedOsnap(pt1, "midp", pt2);
    Следующий запрос ищет или midpoint или оконечную точку линии, или центра дуги или круга —, какой бы ни - самый близкий pt1.
    acedOsnap(pt1, "midp,endp,center", pt2);
    Третий параметр (pt2 в примерах) установлен в поспешную точку, если найдены. AcedOsnap () функциональные возвращения RTNORM, если точка найдена.
    ОБРАТИТЕ ВНИМАНИЕ, что  переменная системы APERTURE определяет допустимую близость выбранной точки к примитиву при использовании Объектной Привязки.

    Объектные Ссылки

    Объектная ссылка может быть или интенсивно или программное обеспечение, и это может быть или ссылка монопольного использования или ссылка указателя. Жесткое или мягкое различие указывает,является ли упомянутый объект необходимым для существования объекта, который обращается{*относится*} к этому. Жесткая ссылка указывает, что объект зависит от упомянутого объекта для его выживания. Мягкая ссылка указывает, что объект имеет некоторые отношения к упомянутому объекту, но это - не существенное{*необходимое*}.
    Ссылка монопольного использования диктует, как объекты зарегистрированы. Если один объект имеет другой, то всякий раз, когда первый объект зарегистрирован из, требуется находящийся в собственности объект с этим. Поскольку объект может иметь только одного владельца, ссылки{*справочники*} монопольного использования используются для неизбыточного письма из базы данных. Напротив, ссылки{*справочники*} указателя используются, чтобы выразить любую произвольную ссылку{*справочники*} между объектами AcDb.
    Ссылки{*справочники*} Указателя используются для законченного (избыточного) письма из базы данных.
    Например, в следующем числе{*рисунке*}, сдвоенные линии указывают ссылки{*справочники*} монопольного использования.
    Если Вы следуете за сдвоенными линиями, Вы касаетесь каждого объекта в этой маленькой базе данных только однажды. Если Вы также следуете за одиночными линиями, которые представляют ссылки{*справочники*} указателя, Вы касаетесь некоторых объектов больше чем однажды, потому что множественные объекты могут указывать на тот же самый объект. Чтобы получить полное “определение” объекта AcDbLine, Вы были бы должны следовать за всеми жесткими ссылками{*справочниками*}, и монопольное использование и указатель (то есть оба сингл и двойные сплошные линии).
    Объектные Ссылки

    Объектные точки привязки

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

    Mode
    Description
    kOsModeEnd
    Endpoint
    kOsModeMid
    Midpoint
    kOsModeCen
    Center
    kOsModeNode
    Node
    kOsModeQuad
    Quadrant
    kOsModeIns
    Insertion
    kOsModePerp
    Perpendicular
    kOsModeTan
    Tangent
    kOsModeNear
    Nearest

    Сигнатура для AcDbEntity:: getOsnapPoints ()
    virtual Acad::ErrorStatus
    AcDbEntity::getOsnapPoints(
    AcDb::OsnapMode osnapMode,
    int gsSelectionMark,
    const AcGePoint3d& pickPoint,
    const AcGePoint3d& lastPoint,
    const AcGeMatrix3d& viewXform,
    AcGePoint3dArray& snapPoints,
    AcDbIntArray& geomIds) const;
    GeomIds параметр в настоящее время не используется. Перекрестная объектная изюминка не использует эту функцию.

    Объекты Размещения

    Информация относительно размещений сохранена в образцах AcDbLayout класса. Объект размещения содержит печать и информацию параметров настройки составления графика, необходимую, чтобы печатать желательную часть рисунка. Например, объект размещения содержит графическое устройство, размер носителей, графическую область, и графическое вращение, также как несколько других атрибутов, что справка определяет область, которая будет напечатана.
    AcDbLayout объекты сохранены в ACAD_LAYOUT словаре в пределах словари имен объектов базы данных. Имеется один объект AcDbLayout в размещение пространства листа, также как сингл AcDbLayout для пространства модели. Каждый объект AcDbLayout содержит объект ID его связанного AcDbBlockTableRecord. Это заставит это облегчить, чтобы найти запись таблицы блоков, в которой фактическая геометрия размещения постоянно находится. Если AcDbBlockTableRecord представляет размещение, то это содержит объект ID его связанного объекта AcDbLayout.
    Большинство графической информации для объектов размещения сохранено в AcDbPlotSettings, базовый класс AcDbLayout. Вы можете создавать названные графические параметры настройки и использовать их, чтобы инициализировать другие объекты AcDbLayout. Это позволяет Вам экспортировать и импортировать графические параметры настройки от одного размещения до другого. Эти названные графические параметры настройки сохранены в образцах AcDbPlotSettings класса. Имеется один объект AcDbPlotSettings для каждой названной установки графика, и они сохранены в ACAD_PLOTSETTINGS словаре в пределах словари имен объектов.
    ОБРАТИТЕ ВНИМАНИЕ, что не имеется никакого прямого подключения{*связи*} между объектами AcDbLayout в ACAD_LAYOUT словаре и объектах AcDbPlotSettings в ACAD_PLOTSETTINGS словаре.

    Объявление и определение классов расширения протокола

    Пример, включенный в конце этой главы обеспечивает простую иллюстрацию расширения протокола. Это определяет “температурный” класс расширения протокола собственности. Заданное по умолчанию выполнение определено для AcDbEntity, и определенные выполнение определены для AcDbCircle и AcDbRegion.
    Пример обслуживает как модель для более сложный (и реалистический) использования ObjectARX механизма расширения протокола. Базовый класс для этого расширения протокола, названного AsdkEntTemperature, получен из AcRxObject. Этот класс определяет виртуальные функции, которые будут унаследованы полученными классами расширения протокола, AsdkDefaultTemperature, AsdkCircleTemperature, и AsdkRegionTemperature. В этом примере, имеется только одна функция: reflectedEnergy().
    Иерархия классов для классов расширения протокола показывается в следующем рисунке:
    Объявление и определение классов расширения протокола
    Первый шаг в использование расширения протокола должен объявлять и определить каждый из классов расширения протокола. Базовый класс, AsdkEntTemperature, является абстрактным классом, который определен, используя ACRX_NO_CONS_DEFINE_MEMBERS () макрокоманда. Этот класс будет в конечном счете зарегистрирован как часть ObjectARX
    иерархии классов.
    Дочерние классы определены, используя стандартный синтаксис C++ для наследования новых классов. Эти классы не должны быть зарегистрированы в ObjectARX
    иерархии классов, так что Вы не должны использовать макрокоманды ObjectARX
    для них.
    Для каждого класса, Вы осуществляете функции, которые составляют расширение протокола. В этом примере, каждый класс имеет только одну функцию, reflectedEnergy(), который вычисляет температуру для примитива.

    Обязательные объекты Базы данных

    Поскольку объекты созданы в AutoCAD, они добавлены к соответствующему контейнерному объекту в его базе данных. Объекты добавлены к записям в блочной таблице. Записи Таблицы идентификаторов добавлены к соответствующим таблицам идентификаторов. Все другие объекты добавлены к словарю имен объектов или к объектам, которые принадлежат другим объектам (и, в конечном счете, тем же словарям), или к словарю расширения. Сценарий в следующем разделе – “Создании Объектов в AutoCAD, ” детализирует этот процесс. Словари Расширений обсуждены в разделе “Словарь Расширения” на странице 89.
    Чтобы быть пригодной для использования, база данных должна иметь по крайней мере следующий набор объектов:
    · набор девяти таблиц идентификаторов, который включает блочную таблицу, таблицу уровня, и linetype таблицу. Блочная таблица первоначально содержит три записи: *MODEL_SPACE, и два пространства листа, называемые *PAPER_SPACE и *PAPER_SPACE0. Эти блочные записи таблицы представляют модельное пространство и два предопределенных бумажных пространственных размещения. Таблица уровня первоначально содержит одну запись - уровень 0. Linetype таблица первоначально содержит тип линии CONTINUES.
    · объектный словарь имен. Когда база данных создана, этот словарь уже содержит четыре словаря баз данных: словарь GROUP, MLINE, LAYER, и PLOT. В пределах словаря стиля MLINE, стиль STANDART - всегда существует.
    Эти объекты могут быть автоматически созданы в новой базе данных при параметре  kTrue в конструкторе buildDefaultDrawing. Принятие KFalse создает пустую базу данных, в которую DWG или DXF ™ файл может быть загружен.

    ObjectARX функциональные коды типа результата

    Следующие коды типа результата - коды состояния, возвращенные большинством ObjectARX глобальные функции, чтобы указать успех, отказ{*неудачу*}, или специальные условия (типа отмены пользователя):
    Коды результата Библиотечной функции


    Код

     Описание

    RTNORM

     Пользователь ввел имеющее силу значение

    RTERROR

     Функциональный запрос потерпел неудачу

    RTCAN

     Пользователь ввел ESC

    RTREJ

     AutoCAD отклонил запрос как недействительный

    RTFAIL

     Связь AutoLISP потерпела неудачу

    RTKWORD

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

    Значения этих кодов, полученных в итоге в таблице, следующие:


    RTNORM

     Библиотечная функция преуспела.

    RTERROR

     Библиотечная функция не преуспевала; это столкнулось с восстанавливаемой ошибкой.

    Условие RTERROR исключительно из следующих специальных случаев:


    RTCAN

     Пользователь AutoCAD ввел ESC, чтобы отменить запрос. Этот код возвращен вводом пользователя (acedGetxxx) функции и следующими функциями: acedCommand, acedCmd, acedEntSel, acedNEntSelP, acedNEntSel, и acedSSGet.

    RTREJ

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

    RTFAIL

     Связь с AutoLISP потерпела неудачу. Это - фатальная ошибка, которая вероятно означает, что AutoLISP больше не выполняется правильно. Если это обнаруживает эту ошибку, приложение должно выйти. (Не все приложения проверяют этот код, потому что условия, которые могут вести к этому, вероятно,  приведут к зависанию AutoCAD, так или иначе.)

    RTKWORD

     Пользователь AutoCAD ввел ключевое слово или произвольный ввод вместо другого значения (типа точки). Ввод пользователя acedGetxxx () функции, также как acedEntSel, AcedEntSelP, acedNEntSel, и acedDragGen, возвращают этот код результата.

    ОБРАТИТЕ ВНИМАНИЕ Не, все ObjectARX глобальные функции возвращают эти коды состояния; некоторые возвращаемые значения непосредственно. Также, ввод пользователя (acedGetxxx, acedEntSel, acedEntSelP, acedNEntSel, и acedDragGen) функции могут возвращать код типа результата RTNONE, и acedDragGen () указывает произвольный ввод,  возвращая RTSTR вместо RTKWORD.

    ObjectARX Классы Размещения

    Основные классы, вовлеченные в создание и управление размещениями - следующее:
  • AcDbLayout

  • AcDbPlotSettings

  • AcDbPlotSettingsValidator

  • AcDbLayoutManager

  • AcApLayoutManager

  • AcDbLayoutManagerReactor

  • AcDbLayout, AcDbPlotSettings, и AcDbPlotSettingsValidator используются, чтобы создавать и установить атрибуты на объектах размещения. AcDbLayoutManager, AcApLayoutManager, и AcDbLayoutManagerReactor используются, чтобы управлять объектами размещения и исполнять другие связанные размещением задачи. Следующие разделы обеспечивают краткий обзор некоторых из этих классов. Для получения дополнительной информации, см. ObjectARX Ссылку. Для примера использования ObjectARX классов размещения, см., что  lmgrtest.arx производит выборку приложения в ObjectARX, производит выборку каталога.

    ObjectDBX Библиотечные Изменения

    Много библиотек были переименованы, чтобы включить их номер версии. В добавлении, имеются несколько новых библиотек. Следующие перекрестные ссылки таблицы новые и старые библиотечные названия.
    ObjectDBX библиотеки


    Release 14 Library Name

    AutoCAD 2000 Library Name

    acfirst.dll

    ac1st15.dll

    ism.lib

    acISMobj15.lib

    libacge.lib

    acge15.lib

    libacgex.lib

    acgex15.lib

    libacbr.lib

    acbr15.lib

    Not present

    achapi15.lib

    Not present

    acdb15.lib

    Not present

    acrx15.lib

    Not present

    acutil15.lib

    При соединении ведущих приложений, убедитесь, что связали acdb15.lib сначала, rxapi.lib вторым и любые другие библиотеки впоследствии.
    Класс сервиса приложения
    Когда ObjectDBX используется, чтобы создать ведущее приложение, код в ObjectDBX библиотеке ожидает, что  ведущее приложение обеспечит это некоторыми услугами; например, файл находит механизм. Когда Вы записываете ObjectDBX
    ведущее приложение, Вы требованы, чтобы осуществить эти услуги, которые будут использоваться и,  ObjectDBX
    непосредственно, и потенциально другими приложениями DBX.
    Эти назначения и услуги сделаны доступными прикладным объектным классом AcDbHostApplicationServices. Ваше ведущее приложение должно получить, создавать, и регистрировать образец этого класса с ObjectDBX, который в свою очередь вызывает функции члена образца класса как необходимо.
    Файл заголовка для прикладных услуг - dbapserv.h. Классы и методы в этом файле заголовка относятся к одной из трех категорий:
    § Те Вы должен перегрузить, потому что никакое заданное по умолчанию выполнение не обеспечивается как метод,  принят, чтобы быть очень специфичным для приложения. Они, как объявляют,  являются чистыми виртуальными.
    § Те Вы можете перегружать, но это имеет заданное по умолчанию выполнение, которое минимально удовлетворит код базы данных. Они объявлены виртуальными.
    § Те Вы не можете перегружать, поскольку они, как ожидается,  будут работать тождественно во всех ведущих приложениях. Они вообще объявляются не виртуальными.
    Это требовано, что любое ObjectDBX ведущее приложение должно обеспечить класс, полученный из AcDbHostApplicationServices. Это отличается от пути DWG Отключенный, работал, где заданное по умолчанию обслуживание обеспечивалось. Детальное описание класса существует в ObjectARX Ссылке, где каждый метод описан с его заданным по умолчанию выполнением (если это имеет один), что Вы должны делать, чтобы перегрузить метод успешно, и как вызвать метод. Когда ваше приложение инициализирует, это должно создать образец вашего класса, полученного из AcDbHostApplicationServices. Конфигурируйте это, по мере необходимости и делайте объект доступным приложению,  вызывая глобальную функцию acdbSetHostApplicationServices ().

    Оболочка (Shell)

    Оболочка - список лиц, которые могли бы быть связаны и могут иметь отверстия в них.
    Оболочка определена числом уникальной вершины, список вершины (pVertexList), число лиц (faceListSize), и списка лица, который состоит из числа точек в данном лице, сопровождаемом индексом в списке вершины каждой вершины для того лица. Cигнатура для Shell () функция
    virtual Adesk::Boolean
    AcGiWorldGeometry::shell(
    const Adesk::UInt32 nbVertex,
    const AcGePoint3d* pVertexList,
    const Adesk::UInt32 faceListSize,
    const Adesk::Int32* pFaceList,
    const AcGiEdgeData* pEdgeData = NULL,
    const AcGiFaceData* pFaceData = NULL,
    const AcGiVertexData* pVertexData = NULL
    const struct
    resbuf*pResBuf = NULL) const = 0;
    Отрицательный индекс вершины указывает отверстие в оболочке. Отверстия должны быть в том же самом плане как лицо, в котором они постоянно находятся. Отверстия не должны коснуться друг друга и должны быть полностью внутри содержащего лица. Оболочка () функция - дорогостоящая операция, потому что это требует использования триангуляции, чтобы ломать{*нарушить*} содержащее лицо и отверстия вниз в составляющие треугольники.
    AcGi многоугольники и оболочки с лицами пять или большим количеством сторон также разрушены в треугольники прежде, чем послались, чтобы быть отображенным. Наличие AcGi триангулирует многоугольник, или лицо оболочки может быть дорогостоящее в терминах памяти и скорости, так что это рекомендует, чтобы Вы использовали три - или четыре - sided лица в оболочках, чтобы создать лица или многоугольники с пять или большее количество сторон. Тем путем, примитив не будет помещен через медленный шаг триангуляции.
    ОБРАТИТЕ ВНИМАНИЕ, что  триангуляция используется только на многоугольниках пяти сторон или больше, лица оболочки пяти сторон или больше, лица оболочки с отверстиями, и заполнена текст.
    Вершина в данном лице должна быть компланарна. Не имеется никакой подразумеваемой связности между лицами.
    Данные Края для оболочки перечислены в порядке, подразумеваемом списком лица. Например, в первом лице, vertex0 к vertex1 определяет,  первый край, vertex1 к vertex2 определяет второй край, и так далее до последней вершины лица, которое соединяется с первой вершиной, как показано ниже.

    Оболочка (Shell)

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

    Порядок данных лица, если есть, следует за упорядочением списка лица для оболочки.

    Следующее - пример оболочки с цветными данными, приложенными к граням и стоит и данным видимости, приложенным к граням. Оболочка составлена из двух треугольников в различных планах, которые совместно используют общий край. Общий край имеет видимость силуэта. Это означает, что, когда команда HIDE - в действительности и переменная AutoCAD DISPSILH равняется 1 (силуэты дисплея включены), общий край между лицами оттянут только, если оба лица в области просмотра находятся на той же самой стороне общего края. В этом случае, одно лицо - позади другой, так что это не рисует:

    Adesk::Boolean

    AsdkShellSamp::worldDraw(AcGiWorldDraw* pW)

    {

    // Fill the faces with the current color.

    //

    pW->subEntityTraits().setFillType(kAcGiFillAlways);

    // Create vertices.

    //

    Adesk::UInt32 numVerts = 4;

    AcGePoint3d *pVerts = new AcGePoint3d[numVerts];

    pVerts[0] = AcGePoint3d(0.0, 0.0, 0.0);

    pVerts[1] = AcGePoint3d(0.0, 1.0, 0.0);

    pVerts[2] = AcGePoint3d(1.0, 1.0, 0.0);

    pVerts[3] = AcGePoint3d(1.0, 0.0, 2.0);

    // Create two faces.

    //

    Adesk::UInt32 faceListSize = 8;

    Adesk::Int32 *pFaceList

    = new Adesk::Int32[faceListSize];

    // Assign vertices for face 1.

    //

    pFaceList[0] = 3; // Three vertices in the face

    pFaceList[1] = 0; // pVerts[0]

    pFaceList[2] = 1; // pVerts[1]

    pFaceList[3] = 2; // pVerts[2]

    // Assign vertices for face 2.

    //

    pFaceList[4] = 3; // Three vertices in the face

    pFaceList[5] = 0; // pVerts[0]

    pFaceList[6] = 2; // pVerts[2]

    pFaceList[7] = 3; // pVerts[3]

    // Apply colors to edges.

    //

    AcGiEdgeData edgeData;

    int numEdges = 6;

    short *pEdgeColorArray = new short[numEdges];

    pEdgeColorArray[0] = kRed;

    pEdgeColorArray[1] = kYellow;

    pEdgeColorArray[2] = kGreen;


    pEdgeColorArray[3] = kCyan;

    pEdgeColorArray[4] = kBlue;

    pEdgeColorArray[5] = kMagenta;

    edgeData.setColors(pEdgeColorArray);

    // Apply visibility to edges and make the common edge

    // between two faces have silhouette visibility during

    // the HIDE command with AutoCAD variable DISPSILH = 1.

    //

    Adesk::UInt8 *pEdgeVisArray

    = new Adesk::UInt8[numEdges];

    edgeData.setVisibility(pEdgeVisArray);

    pEdgeVisArray[0] = kAcGiVisible;

    pEdgeVisArray[1] = kAcGiVisible;

    pEdgeVisArray[2] = kAcGiSilhouette;

    pEdgeVisArray[3] = kAcGiSilhouette;

    pEdgeVisArray[4] = kAcGiVisible;

    pEdgeVisArray[5] = kAcGiVisible;

    // Apply colors to faces.

    //

    AcGiFaceData faceData;

    int numFaces = 2;

    short *pFaceColorArray = new short[numFaces];

    pFaceColorArray[0] = kBlue;

    pFaceColorArray[1] = kRed;

    faceData.setColors(pFaceColorArray);

    pW->geometry().shell(numVerts, pVerts, faceListSize,

    pFaceList, &edgeData, &faceData);

    delete [] pVerts;

    delete [] pFaceList;

    delete [] pEdgeColorArray;

    delete [] pFaceColorArray;

    return Adesk::kTrue;

    }

    Объект AcGiVertexData содержит единственный флажок, который определяет, как вершина в оболочке упорядочивается. Этот флажок установлен и делается запрос со следующими функциями:

    virtual void

    AcGiVertexData::setOrientationFlag(AcGiOrientationType oflag);

    virtual AcGiOrientationType

    AcGiVertexData::orientationFlag() const;

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

    § kAcGiClockwise

    § kAcGiCounterClockwise

    § kAcGiNoOrientation

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

    Обрабатывающие примитив Функции

    Следующие обрабатывающие примитив функции не могут быть вызваны, в то время как диалоговое окно активно:
    §
    acdbEntMod ()
    § acdbEntMake ()
    § acdbEntDel ()
    § acedEntSel ()
    § acedNEntSel ()
    § acedNEntSelP ()
    § acdbEntUpd ()

    Обработка Наборов Выбора

    Функции ObjectARX, которые обрабатывают наборы выбора,  подобны тем в AutoLISP. AcedSSGet () функция обеспечивает большинство общих средств создания набора выборов. Это создает набор выборов способом из трех путей:
    §
    Подсказка пользователя, чтобы выбрать объекты.
    § Явно определяющий примитивы, чтобы выбрать,  используя набор PICKFIRST или Пересечение, Многоугольник Пересечения, Заграждающую метку, Последнюю{*прошлую*}, Предыдущую, Окно, или опции Window Polygon (как в интерактивном использовании AutoCAD), или,  определяя одиночную точку или заграждающую метку точек.
    § Фильтрация базы данных текущего рисунка,  определяя список атрибутов и условий, которым выбранные примитивы должны соответствовать. Вы можете использовать фильтры с любой из предыдущих опций.
    int
    acedSSGet (
    const char *str,
    const void *pt1,
    const void *pt2,
    const struct resbuf *entmask,
    ads_name ss);
    Первый параметр к acedSSGet () - строка, которая описывает которые опции выбора использовать, как получено в итоге в следующей таблице.
    Selection options for acedSSGet

    Selection
     Code Description
    NULL
    Single-point selection (if pt1 is specified) or user selection (if pt1 is also NULL)
    #
     Nongeometric (all, last, previous)
    :$
    Prompts supplied
    .
    User p ick
    :?
     Other callbacks
    A
    All
    B
    Box
    C
    Crossing
    CP
    Crossing Polygon
    :D
     Duplicates OK
    :E
     Everything in aperture
    F
     Fence
    G
     Groups
    I
     Implied
    :K
     Keyword callbacks
    L
     Last
    M
     Multiple
    P
     Previous
    :S
     Force single object selection only
    W
    Window
    WP
     Window Polygon
    X
     Extended search (search whole database)

    Следующие два параметра определяют значения точки для уместных опций. (Они должны быть NULL, если они не применяются.) Если четвертый параметр, entmask, - не NULL, это указывает на список значений поля примитива, используемых в фильтрации. Пятый параметр, ss, идентифицирует имя набора выбора.

    Следующий код показывает представителю, вызывает к acedSSGet (). Как acutBuildList () запрос иллюстрирует, для “CP” опций многоугольника, и “ПОДГОТОВКА ТЕКСТОВ” (но не для “F”), acedSSGet () автоматически закрывает список точек. Вы не должны формировать список, который определяет конечную точку, идентичную первому.

    ads_point pt1, pt2, pt3, pt4;

    struct resbuf *pointlist;

    ads_name ssname;

    pt1[X] = pt1[Y] = pt1[Z] = 0.0;

    pt2[X] = pt2[Y] = 5.0; pt2[Z] = 0.0;

    // Get the current PICKFIRST set, if there is one;

    // otherwise, ask the user for a general entity selection.

    acedSSGet(NULL, NULL, NULL, NULL, ssname);

    // Get the current PICKFIRST set, if there is one.

    acedSSGet("I", NULL, NULL, NULL, ssname);

    // Selects the most recently selected objects.

    acedSSGet("P", NULL, NULL, NULL, ssname);

    // Selects the last entity added to the database.

    acedSSGet("L", NULL, NULL, NULL, ssname);

    // Selects entity passing through point (5,5).

    acedSSGet(NULL, pt2, NULL, NULL, ssname);

    // Selects entities inside the window from (0,0) to (5,5).

    acedSSGet("W", pt1, pt2, NULL, ssname);

    // Selects entities enclosed by the specified polygon.

    pt3[X] = 10.0; pt3[Y] = 5.0; pt3[Z] = 0.0;

    pt4[X] = 5.0; pt4[Y] = pt4[Z] = 0.0;

    pointlist = acutBuildList(RTPOINT, pt1, RTPOINT, pt2,

    RTPOINT, pt3, RTPOINT, pt4, 0);

    acedSSGet("WP", pointlist, NULL, NULL, ssname);

    // Selects entities crossing the box from (0,0) to (5,5).

    acedSSGet("C", pt1, pt2, NULL, ssname);

    // Selects entities crossing the specified polygon.

    acedSSGet("CP", pointlist, NULL, NULL, ssname);

    acutRelRb(pointlist);

    // Selects the entities crossed by the specified fence.

    pt4[Y] = 15.0; pt4[Z] = 0.0;

    pointlist = acutBuildList(RTPOINT, pt1, RTPOINT, pt2,

    RTPOINT, pt3, RTPOINT, pt4, 0);

    acedSSGet("F", pointlist, NULL, NULL, ssname);

    acutRelRb(pointlist);


    Дополнение acedSSGet () - acedSSFree (), который выпускает набор выборов, как только приложение закончило использовать это. Набор выборов определен по имени. Следующий кодовый фрагмент использует ads_name объявление от предыдущего примера.

    acedSSFree(ssname);

    ПРИМЕЧАНИЕ AutoCAD не может иметь больше чем 128 наборов выбора, открытые сразу. Этот предел включает наборы выбора, открытые всего одновременно выполняющиеся приложения ObjectARX и AutoLISP. Предел может быть отличен на вашей системе. Если предел достигнут, AutoCAD отказывается создавать большее количество наборов выбора. Одновременно управление большим количеством наборов выбора не рекомендуется. Вместо этого, сохраните разумное число наборов, открытых в любое данное время, и вызовите acedSSFree () чтобы освободить неиспользованные наборы выбора как можно скорее. В отличие от AutoLISP, ObjectARX среда не имеет никакой автоматической сборки "мусора", чтобы освободить наборы выбора после того, как они использовались. Приложение должно всегда освобождать его открытые наборы выбора, когда это получает kUnloadDwgMsg, kEndMsg, или kQuitMsg сообщение.

    Обработка окна редактирования

    Действия и повторные вызовы, чтобы обработать окна редактирования подобны тем для слайдеров.
    Однако, так как символы в окнах редактирования уже видимы, не имеется никакой потребности в действии на промежуточных результатах.
    Следующие типовые проверки программы значение но не восстанавливают изображение этого:
    static void CALLB
    edit_action(ads_callback_packet *cbpkt)
    {
    int reason = cbpkt->reason;
    if ((reason == CBR_LOST_FOCUS) || (reason == CBR_SELECT)) {
    // Check range, syntax, etc. on transient value.
    //
    ...
    }
    }
    Чтобы показывать альтернативу, этот пример проверяет CBR_LOST_FOCUS скорее чем CBR_DOUBLE_CLICK.

    Обработка Ошибок от Вызванных Функций

    Когда acedInvoke() возвращает RTNORM, это подразумевает, что внешняя функция была вызвана и возвращена успешно. Это не подразумевает, что внешняя функция успешно получила результат; чтобы получить эту информацию, ваша программа должна осмотреть параметр результата. Если внешняя функция успешна и предполагается к возвращаемым значениям, результат указывает на список буфера результата, содержащий один или большее количество значений. Если внешняя функция потерпела неудачу, параметр результата установлен в NULL.
    Параметр результата - также NULL, если внешняя функция не возвращает результат.
    Следующий типовой кодовый фрагмент проверяет возвращаемое значение внешней функции, которая, как ожидается,  возвратится один или большее количество значений результата:
    struct resbuf *xfcnlist, *xresults;
    // Build the invocation list, xfcnlist.
    rc = acedInvoke(xfcnlist, &xresults);
    if (rc != RTNORM) {
    // Couldn't call the function—report this error (or even abort).
    return BAD;
    }
    if (xresults == NULL) {
    // Function was called but returned a bad result.
    return BAD;
    }
    // Look at return results and process them.

    Обработка ошибок

    Примеры в этом руководстве опустили необходимую проверку ошибок, чтобы упростить код. Однако, вы будете всегда хотеть проверить состояние возвращения и брать соответствующее действие. Следующий пример показывает соответствующему использованию проверки ошибок для нескольких примеров, показанных сначала в главе 2, “ Учебник для начинающих Базы данных. ”
    Acad::ErrorStatus
    createCircle(AcDbObjectId& circleId)
    {
    circleId = AcDbObjectId::kNull;
    AcGePoint3d center(9.0, 3.0, 0.0);
    AcGeVector3d normal(0.0, 0.0, 1.0);
    AcDbCircle *pCirc = new AcDbCircle(center, normal, 2.0);
    if (pCirc == NULL)
    return Acad::eOutOfMemory;
    AcDbBlockTable *pBlockTable;
    Acad::ErrorStatus es =
    acdbHostApplicationServices()->workingDatabase()->
    getSymbolTable(pBlockTable, AcDb::kForRead);
    if (es != Acad::eOk) {
    delete pCirc;
    return es;
    }
    AcDbBlockTableRecord *pBlockTableRecord;
    es = pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);
    if (es != Acad::eOk) {
    Acad::ErrorStatus es2 = pBlockTable->close();
    if (es2 != Acad::eOk) {
    acrx_abort("\nApp X failed to close Block" " Table. Error: %d", acadErrorStatusText(es2));
    }
    delete pCirc;
    return es;
    }
    es = pBlockTable->close();
    if (es != Acad::eOk) {
    acrx_abort("\nApp X failed to close Block Table."
    " Error: %d", acadErrorStatusText(es));
    }
    es = pBlockTableRecord->appendAcDbEntity(circleId,
    pCirc);
    if (es != Acad::eOk) {
    Acad::ErrorStatus es2 = pBlockTableRecord->close();
    if (es2 != Acad::eOk) {
    acrx_abort("\nApp X failed to close"
    " Model Space Block Record. Error: %s",
    acadErrorStatusText(es2));
    }
    delete pCirc;
    return es;
    }
    es = pBlockTableRecord->close();
    if (es != Acad::eOk) {
    acrx_abort("\nApp X failed to close"
    " Model Space Block Record. Error: %d",
    acadErrorStatusText(es));
    }
    es = pCirc->close();
    if (es != Acad::eOk) {
    acrx_abort("\nApp X failed to"
    " close circle entity. Error: %d",

    acadErrorStatusText(es));

    }

    return es;

    }

    Acad::ErrorStatus

    createNewLayer()

    {

    AcDbLayerTableRecord *pLayerTableRecord

    = new AcDbLayerTableRecord;

    if (pLayerTableRecord == NULL)

    return Acad::eOutOfMemory;

    Acad::ErrorStatus es

    = pLayerTableRecord->setName("ASDK_MYLAYER");

    if (es != Acad::eOk) {

    delete pLayerTableRecord;

    return es;

    }

    AcDbLayerTable *pLayerTable;

    es = acdbHostApplicationServices()->workingDatabase()->

    getSymbolTable(pLayerTable, AcDb::kForWrite);

    if (es != Acad::eOk) {

    delete pLayerTableRecord;

    return es;

    }

    // The linetype object ID default is 0, which is

    // not a valid ID. Therefore, it must be set to a

    // valid ID, the CONTINUOUS linetype.

    // Other data members have valid defaults, so

    // they can be left alone.

    //

    AcDbLinetypeTable *pLinetypeTbl;

    es = acdbHostApplicationServices()->workingDatabase()->

    getSymbolTable(pLinetypeTbl, AcDb::kForRead);

    if (es != Acad::eOk) {

    delete pLayerTableRecord;

    es = pLayerTable->close();

    if (es != Acad::eOk) {

    acrx_abort("\nApp X failed to close Layer"

    " Table. Error: %d",

    acadErrorStatusText(es));

    }

    return es;

    }

    AcDbObjectId ltypeObjId;

    es = pLinetypeTbl->getAt("CONTINUOUS", ltypeObjId);

    if (es != Acad::eOk) {

    delete pLayerTableRecord;

    es = pLayerTable->close();

    if (es != Acad::eOk) {

    acrx_abort("\nApp X failed to close Layer"

    " Table. Error: %d",

    acadErrorStatusText(es));

    }

    return es;

    }

    pLayerTableRecord->setLinetypeObjectId(ltypeObjId);

    es = pLayerTable->add(pLayerTableRecord);

    if (es != Acad::eOk) {

    Acad::ErrorStatus es2 = pLayerTable->close();

    if (es2 != Acad::eOk) {

    acrx_abort("\nApp X failed to close Layer"

    " Table. Error: %d",

    acadErrorStatusText(es2));

    }

    delete pLayerTableRecord;

    return es;

    }

    es = pLayerTable->close();

    if (es != Acad::eOk) {

    acrx_abort("\nApp X failed to close Layer"

    " Table. Error: %d",

    acadErrorStatusText(es));

    }

    es = pLayerTableRecord->close();

    if (es != Acad::eOk) {

    acrx_abort("\nApp X failed to close Layer"

    " Table Record. Error: %d",

    acadErrorStatusText(es));

    }

    return es;

    }

    Обработка Радио-Кластеров

    "Радио" кнопки появляются в кластерах радио. Значение каждой индивидуальной "радио" кнопки является или “1” для на или “0” для от; значение кластера радио - ключевой атрибут в настоящее время отобранной кнопки. Пакет PDB управляет значениями "радио" кнопок в кластере, и гарантирует, что только каждый находится на одновременно.
    Вы можете назначать действие на каждую индивидуальную "радио" кнопку, но это более удобно назначить действие на кластер радио в целом и затем проверять значение кластера, чтобы видеть, который из "радио" кнопок был выбран.
    В следующем примере, радио кластеризует средство управления, которое вид трехмерного объекта отображено после того, как пользователь оставляет диалоговое окно. Этот кластер содержит четыре "радио" кнопки (хотя имелся бы больше).
    ads_action_tile(hdlg, "view_sel", pick_view);
    ...
    static void CALLB
    pick_view(ads_callback_packet *cbpkt)
    {
    char value[TILE_STR_LIMIT];
    strcpy(value, cbpkt->value);
    if (strcmp(value, "front") == 0)
    show_which = 0;
    else if (strcmp(value, "top") == 0)
    show_which = 1;
    else if (strcmp(value, "left") == 0)
    show_which = 2;
    else if (strcmp(value, "right") == 0)
    show_which = 3;
    }
    Предшествующие примеры показывают каждую "радио" кнопку, связанную с единственной переменной, которая берет множественные значения. Они могут также вызывать дополнительные действия, типа отключения выборов в вашем диалоговом окне. Если кластер радио - большой, удобно сохранить связанные значения в таблице. Если Вы используете таблицу, структурируете это так, чтобы это не зависело от порядка кнопок в пределах кластера. Пакет PDB не налагает это ограничение, и порядок может изменяться, если DCL изменяется.

    Обработка Символьного типа

    ObjectARX обеспечивает пакет обрабатывающих символа функций, как показано в таблице, которая следует. Преимущество этого пакета по пакету стандартной библиотеки для C, ctype.h, состоит в том, что эти функции являются независимыми от любого определенного набора символов и не связаны к ASCII. Они настроены к потоку конфигурация языка AutoCAD. В других отношениях, они ведут себя подобно их стандартным копиям C.
    Функции Символьного типа


    Имя функции

    Цель

    AcutIsAlpha

     Проверяет, что символ алфавитный

    AcutIsUpper

     Проверяет, что символ верхнего регистра

    AcutIsLower

     Проверяет, что символ - нижний регистр

    AcutIsDigit

     Проверяет, что символ - цифра

    AcutIsXDigit

     Проверяет, что символ - шестнадцатеричная цифра

    AcutIsSpace

     Проверяет, что символ - символ незаполненного пространства

    AcutIsPunct

     Проверяет, что символ - символ пунктуации

    AcutIsAlNum

     Проверяет, что символ алфавитно-цифровой

    AcutIsPrint

     Проверяет, что символ печатаем

    AcutIsGraph

     Проверяет, что символ графический

    AcutIsCntrl

     Проверяет, что символ - управляющий символ

    AcutToUpper

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

    AcutToLower

     Преобразовывает символ к нижнему регистру

    Следующий кодовый фрагмент берет символ (значение в этом примере произвольно) и преобразовывает это к верхнему регистру. AcutToUpper () функция не имеет никакого эффекта, если символ - уже верхний регистр.
    int cc = 0x24;
    cc = acutToUpper (cc);

    Обработка Слайдеров

    Когда Вы обрабатываете действия и повторные вызовы от слайдеров, ваше приложение должно проверить код причины, который это получает наряду с повторным вызовом.
    Хотя Вы не требованы, чтобы проверить код причины, рекомендуется, чтобы Вы делали так, чтобы привести обработку. Частота повторных вызовов, что слайдеры генерируют, зависит от платформы, но некоторые платформы генерируют CBR_DRAG повторный вызов для каждого движения мыши поиски слайдера.
    Следующая функция показывает основную схему обрабатывающей слайдера функции.
    Это вызвано от выражения действия, связанного с полем ввода слайдера. Slider_info поле ввода, используемое функцией отображает текущее значение слайдера в десятичной форме. Часто такое поле ввода - окно редактирования также, которое дает пользователю выбор или управления слайдером или печатанием его значения непосредственно. Если пользователь напечатает значение в slider_info, повторный вызов окна редактирования должен (наоборот) модифицировать значение слайдера:
    static void CALLB
    slider_action(ads_callback_packet *cbpkt)
    {
    ads_hdlg hdlg = cbpkt->dialog;
    int reason = cbpkt->reason;
    char interim[TILE_STR_LIMIT];
    // Save the interim result.
    //
    strcpy(interim, cbpkt->value);/
    // Display the result.
    //
    ads_set_tile(hdlg, "slider_info", interim);
    }
    static void CALLB
    ebox_action(ads_callback_packet *cbpkt)
    {
    ads_hdlg hdlg = cbpkt->dialog;
    int reason = cbpkt->reason;
    char interim[TILE_STR_LIMIT];
    // Save the interim result.
    //
    strcpy(interim, cbpkt->value);
    // Display the result.
    //
    ads_set_tile(hdlg, "myslider", interim);
    }

    Обработка Внешних Приложений

    ObjectARX-приложения могут загружать и разгружать другие ObjectARX-приложения и получать,  список которого внешние приложения в настоящее время загружены, также, как программы AutoLISP могут (использование arxloaded). Следующий запрос загружается,  программа вызвала myapp:
    if (acedArxLoad ("myapp") != RTERROR) {
    // Use acedInvoke() to call functions in "myapp".
    }
    Когда ваша программа закончена с myapp, это может разгрузить это,  вызывая
    acedArxUnload("myapp");
    Функция acedArxLoaded() может использоваться, чтобы получить имена всех в настоящее время загруженных приложений, как в следующем коде:
    struct resbuf *rb1, *rb2;
    for (rb2 = rb1 = acedArxLoaded(); rb2 != NULL; rb2 = rb2->rbnext) {
    if (rb2->restype == RTSTR)
    acutPrintf("%s\n", rb2->resval.rstring);
    }
    acutRelRb(rb1);
    Вы можете вызывать функции acedArxLoaded () и acedArxUnload () в конъюнкции друг с другом. Следующий пример разгружает все приложения кроме текущего:
    struct resbuf *rb1, *rb2;
    for (rb2 = rb1 = acedArxLoaded(); rb2 != NULL; rb2 = rb2->rbnext) {
    if (strcmp(ads_appname, rb2->resval.rstring) != 0)
    acedArxUnload(rb2->resval.rstring);
    }
    acutRelRb(rb1);

    и упомянутые примитивы всегда существуют

    Если обращение и упомянутые примитивы всегда существуют в том же самом AcDbBlockTableRecord, это достаточно для обращающегося перегруженного примитива wblock () чтобы отправить isPrimary, оценивают полученное, чтобы вызвать wblock упомянутого примитива (). Это воспользуется преимуществом заданного по умолчанию поведения из всех трех форм WBLOCK, как отмечено в предыдущей секции. Мы не должны быть обеспокоены, с которым тип WBLOCK встречается.

    Имеются два способа перегрузить заданное по умолчанию поведение клона wblock для этого случая. Сначала, Вы могли записывать поверх полный wblockClone () для обращающегося примитива. В типовом коде для заданного по умолчанию выполнения wblockClone () (в предыдущей секции), вы будете видеть цикл на getNextHardObject (). В пределах этого цикла Вы были бы должны прервать упомянутый объект ID и изменять значение isPrimary от Adesk:: kFalse, чтобы быть тем же самый, поскольку значение isPrimary прошло в.

    Однако, намного более простой способ делать это состоит в том, чтобы продолжить использовать по умолчанию wblockClone () для вашего заказного примитива, но клонировать упомянутый примитив сначала, с правильными назначениями, когда настройка по умолчанию isPrimary не была бы правильна. Как только вы клонировали упомянутый примитив, когда Вы вызываете ваш собственный wblockClone (), это будет видеть, что упомянутый примитив уже клонирован и не будет пытаться клонировать это, используя настройки по умолчанию. Следующая выборка демонстрирует это. Компонент данных, mRefEnt, является ссылкой AcDbHardPointerId.

    Acad::ErrorStatus

    AsdkEntity::wblockClone(AcRxObject* pOwner,

    AcDbObject*& pClone,

    AcDbIdMapping& idMap,

    Adesk::Boolean isPrimary) const

    {

    // If isPrimary is kTrue, then override the default cloning

    // within our own cloning, which would set it to kFalse,

    // by cloning our referenced entity first.

    //

    if (isPrimary) {

    Acad::ErrorStatus es;

    AcDbEntity* pEnt;

    es = acdbOpenAcDbEntity(pEnt, mRefEnt, AcDb::kForRead);


    Если Вы создаете заказной объект или с AcDbHardPointerId или жестко закодированной ссылкой AcDbEntity, Вы ответствены за запрос AcDbBlockTableRecord:: appendAcDbEntity () на упомянутом примитиве, когда необходимо в течение wblock (). В этом контексте, жестко закодированная ссылка - любая ситуация, в которой объект заставляет примитив быть включенным в wblockClone () через некоторый заказной код, написанный в приложении.
    Необходимо делать добавление в конец вручную, потому что заданное по умолчанию выполнение AcDbDatabase:: wblockClone () будет всегда устанавливать isPrimary в Adesk:: kFalse при запросе wblockClone() на упомянутых объектах. Если объект - AcDbEntity, эта установка сообщает wblockClone() не добавлять примитив. Однако, как обозначено в предыдущей секции, если мы не делаем  WBLOCK* и клонированный примитив должен занять пространство модели или пространство листа, тогда заданное по умолчанию поведение должно быть перегружено, и добавляющийся должен быть вызван.
    Если Вы позволяете заданному по умолчанию поведению происходить в запросе к wblockClone () примитив, его клон закончится в базе данных, но это будет ownerless. Это не будет добавлено в конец его новому владельцу, и не имеется никакого текущего способа закончить его, чтобы добавить через API. Для упомянутого примитива, который будет добавлен в конец, значение isPrimary должно быть сброшено к Adesk::kTrue перед  запросом его wblockClone() функция.
    Следующий два случая показывают, как можно было обрабатывать жесткую ссылку от заказного объекта до другого примитива. Первый случай более простой, но это требует, чтобы обращение и упомянутые примитивы всегда существовали в том же самом AcDbBlockTableRecord. Второй показывает то, что должно рассмотреться, могут ли эти два примитива существовать в различных записях, или когда ссылка находится в AcDbObject вместо AcDbEntity.


    if (es != Acad::eOk)

    return es;

    // Use the same owner, and pass in the same isPrimary

    // value.

    //

    AcDbObject* pSubClone = NULL;

    es = pEnt->wblockClone(pOwner, pSubClone, idMap, kTrue);

    if (pSubClone != NULL)

    pSubClone->close();

    pEnt->close();

    if (es != Acad::eOk)

    return es;

    }

    // Now we can clone ourselves by calling our parent’s method.

    //

    return AcDbEntity::wblockClone(pOwner, pClone, idMap, isPrimary);

    }

    Обработка жестких ссылок к AcDbEntities в течение wblockClone(): СЛУЧАЙ 2

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

    Сначала, Вы будете должны проверить WBLOCK уведомление, чтобы определить, который тип WBLOCK встречается, вероятно,  устанавливая глобальный флажок, котором можно тогда делать запрос вашим wblockClone () функция:

    § если это - WBLOCK *, не используют AcDbBlockTableRecord:: appendAcDbEntity () в перегрузке заказного класса wblockClone (), в течение повторных вызовов, или в любом другом месте.

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

    1) Всегда клонируйте упомянутые примитивы в пространство модели также. В этом случае, Вы всегда установили бы isPrimary в Adesk:: kTrue, или,


    2) Проверить{*отметить*} текущее местоположение упомянутого примитива. Если это находится в пространстве модели или пространстве листа, клон это к соответствующему пространству и устанавливает isPrimary в Adesk:: kTrue. Если это находится в отобранном блоке, также клонировать это к пространству модели. Если это находится в некотором другом определяемом пользователем блоке, то вызовите wblockClone () на той блочной записи. Только убедитесь, что Вы не пробуете клонировать отобранный блок. В этом случае, запись таблицы блоков будет заботиться о клонировании ваш упомянутый примитив.

    § если это - WBLOCK набора выборов, только сбрасывают isPrimary к Adesk:: kTrue, если упомянутый примитив входит в пространство модели или пространство листа. Если это находится в определяемом пользователем блоке, назовите wblockClone () на этом AcDbBlockTableRecord, вместо на вашем упомянутом примитиве.

    Наконец, должно быть отмечено, что введение жесткой ссылки AcDbEntity в настоящее время не поддержано AcDbProxyObject системой, даже если Вы используете AcDbHardPointerId для ссылки. AcDbProxyObject использует по умолчанию wblockClone () выполнение, и таким образом не будет делать добавляющийся из любых упомянутых примитивов в течение любой формы WBLOCK. Если WBLOCK случается, когда ваши примитивы - proxies, ссылки клонируются, но без добавляющегося они будут ownerless и не постоянны. Результат - то, что, когда рисунок wblocked загружается, ваша ссылка, ID будет NULL, и упомянутый примитив будет отсутствовать. Вы должны закодировать ваш заказной объект, чтобы обработать эту ситуацию изящно.

    Вставка

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


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

    Редактор Функции Уведомления Реактора

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

  • beginDeepClone ()


  • beginDeepCloneXlation ()


  • abortDeepClone ()


  • endDeepClone ()


  • BeginDeepClone () функция вызвана после того, как AcDbIdMapping образец создан и прежде, чем любые объекты клонированы. Карта ID будет пуста, но этом можно делать запрос для destDb () и deepCloneContext () в это время.

    BeginDeepCloneXlation () функция вызвана в конце концов объектов в первичном наборе выборов,  были клонированы и прежде, чем ссылки оттранслированы.

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

    AbortDeepClone () функция вызвана в любое время между beginDeepClone () и endDeepClone ().

    EndDeepClone () функция вызвана в конце процесса трансляции и клонирования. Объектные ID больше не в состоянии непрерывного изменения. Однако, этот запрос не подразумевает, что примитивы находятся в их конечном состоянии для любой команды,  выполняется. Часто клонированные примитивы преобразованы, или другие операции выполнены после клонируемого процесса. Имеются дополнительные функции повторного вызова, которые могут использоваться, чтобы обратиться к примитивам позже, включая commandEnded ().

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

  • beginWblock ()



  • otherWblock ()


  • abortWblock ()


  • endWblock ()


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

    1 beginDeepClone () Этот запрос послан, как только образец адресата АкДбДатабас был создан, но это находится в “необработанном” состоянии и не готово к добавлению в конец.

    2 beginWblock () новая база данных теперь имеет ее основные элементы, типа таблицы метки, класс карта ID, и записи таблицы блоков пространства листа и пространство модели. Это все еще пусто. Клонирование не началось, но новая база данных теперь готова к добавлению в конец.

    3 otherWblock () и beginDeepCloneXlation () Эти два вызывает,  сделаны противовключенным и может использоваться для той же самой цели. Первичный набор объектов был клонирован, но трансляция ссылки не началась все же.

    4 endDeepClone () процесс трансляции теперь закончил, но примитивы - еще не в их конечном состоянии.

    5 endWblock () примитивы теперь были преобразованы, и пространство модели, и начала координат пространства листа были установлены. Новая база данных полна, но еще не была сохранена.

    Имеются три типа AcEditorReactor:: beginWblock (). Они перечислены здесь наряду с их соответствующими функциями AcDbDatabase:

    1 WBLOCK*

    void

    AcEditorReactor:: beginWblock (

    AcDbDatabase* pTo,

    AcDbDatabase* pFrom)

    Acad:: ErrorStatus

     AcDbDatabase::wblock(AcDbDatabase*& POutputDatabase)

    2 WBLOCK определяемого пользователем блока

    void

    AcEditorReactor:: beginWblock (

    AcDbDatabase* pTo,

    AcDbDatabase* pFrom,

    AcDbObjectId blockId)

    Acad:: ErrorStatus

    AcDbDatabase:: wblock (

     AcDbDatabase*& POutputDatabase,

    AcDbObjectId nObjId)

    3 WBLOCK набора выборов

    void

    AcEditorReactor:: beginWblock (

    AcDbDatabase* pTo,

    AcDbDatabase* pFrom,

    const AcGePoint3d& InsertionPoint)

    Acad:: ErrorStatus

    AcDbDatabase:: wblock (

     AcDbDatabase*& POutputDatabase,

    const AcDbObjectIdArray& PIdSet,

    const AcGePoint3d& PPoint3d)


    Все три версии клонируют, и пространство модели и пространство листа AcDbBlockTableRecord перед запросом beginWblock (). Однако, для примитивов в пределах этих записей таблицы блоков, порядок уведомления, будет кажется,  прибывает по-другому в первый тип и последние два типа. В одной версии, примитивы в пространстве модели, которые клонируются,  получит запрос wblockClone() перед AcEditorReactor::beginWblock(). В версиях два и три, примитивы в AcDbBlockTableRecord или наборе выборов получат их wblockClone() запрос после AcEditorReactor::beginWblock() уведомление Запрос.

    Объекты, которые были клонированы в течение частичного XBIND,  автоматически переадресованы только после endDeepClone() уведомление. Это означает, что их AcDbObjectIds во внешне упомянутой базе данных отправлены AcDbObjectIds клонируемых объектов в рисунке главного компьютера, и объекты во внешне упомянутой базе данных удалены. Объекты, что ссылка, на которую отправленный AcDbObjectIds заканчивают ссылаться, имитируют в ведущем рисунке. Если Вы должны отключить это автоматическое переназначение для ваших объектов, то удалите idPair() от idMap, для ваших клонированных объектов, в течение endDeepClone() уведомление.

    Следующая функция вызывает, происходят в течение команды INSERT ИЛИ INSERT*:

    § beginInsert ()

    § otherInsert ()

    § abortInsert ()

    § endInsert ()

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

    1 beginInsert () и beginDeepClone () Они вызывают, возвращаются-to-back и может использоваться для той же самой цели.

    2 otherInsert() и beginDeepCloneXlation() Они вызывают, также возвращаются -to-back и может использоваться для той же самой цели.

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


    4 endInsert() примитивы теперь были преобразованы и были добавлены в конец к блоку. Если это - ВСТАВКА*, они - теперь в пространстве модели и имеют их графику. Они могут использоваться в наборах выбора. Однако, если это - ВСТАВКА, они только были добавлены в конец к записи таблицы блоков; та запись еще не была добавлена к таблице блоков. В этом случае, Вы должны ждать до commandEnded() уведомления, чтобы использовать эти примитивы в наборе выборов.

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

    Это таким образом показывает, как использовать wblock с небытием.

    AcDbIdMapping имеет функцию, deepCloneContext (), который возвращает контекст, в котором глубокая клонируемая функция была вызвана. Контексты - следующее:



    kDcCopy



    Копирование в пределах базы данных; использует COPY, ARRAY, MIRROR (если Вы не удаляете оригинал), приобретение LEADER, или копия INSERT



    kDcExplode



    EXPLODE блок-ссылки



    KDcBlock



    BLOCK создание



    kDcXrefBind



    XREF Связывают, и XBIND



    kDcSymTable



    XREF Слияние Присоединяются, DXFIN, и IGESIN (только записи таблицы идентификаторов клонированы здесь)



    kDcSaveAs



    SAVEAS, когда VISRETAIN установлен в 1 (только записи, таблицы идентификаторов клонированы здесь)



    kDcInsert



    ВСТАВКА рисунка



    kdcWblock



     WBLOCK



    kDcObjects



    AcDbDatabase:: deepCloneObjects ()

    AcEditorReactor::abortDeepClone() функция вызвана, когда запрос к AcDbDatabase::abortDeepClone() сделан.

    Следующий код использует переходного редактора реактор, полученный из AcEditorReactor и перегружает beginDeepCloneXlation () функция для реактора.

    // С тех пор AcDbDatabase::wblock() только поддерживает AcDbEntities в его массиве ID,

    // этот код демонстрирует, как добавить дополнительные объекты в течение beginDeepCloneXlation


    ().

    //  Если это - команда WBLOCK, это спрашивает пользователя, если все текстовые стили были wblocked.

    //  Иначе, только те текстовые стили, упомянутые примитивами, являющимися wblocked

    будут

    //  включены (заданное по умолчанию поведение wblock's).

    //  AsdkEdReactor is derived from AcEditorReactor.

    //

    void

    AsdkEdReactor::beginDeepCloneXlation(AcDbIdMapping& idMap, Acad::ErrorStatus* es)

    {

    if (idMap.deepCloneContext() == AcDb::kDcWblock && getYorN("Wblock all Text Styles"))

    {

    AcDbDatabase *pOrigDb, *pDestDb;

    if (idMap.origDb(pOrigDb) != Acad::eOk)

    return;

    *es = idMap.destDb(pDestDb);

    if (*es != Acad::eOk)

    return;

    AcDbTextStyleTable *pTsTable;

    *es = pOrigDb->getSymbolTable(pTsTable, AcDb::kForRead);

    if (*es != Acad::eOk)

    return;

    AcDbTextStyleTableIterator *pTsIter;

    *es = pTsTable->newIterator(pTsIter);

    if (*es != Acad::eOk) {

    pTsTable->close();

    return;

    }

    AcDbTextStyleTableRecord *pTsRecord;

    AcDbObject *pClonedObj;

    for (; !pTsIter->done(); pTsIter->step()) {

    *es = pTsIter->getRecord(pTsRecord, AcDb::kForRead);

    if (*es != Acad::eOk) {

    delete pTsIter;

    pTsTable->close();

    return;

    }

    // It is not necessary to check for already cloned

    // records. If the text style is already

    // cloned, wblockClone() will return Acad::eOk

    // and pCloneObj will be NULL.

    //

    pClonedObj = NULL;

    *es = pTsRecord->wblockClone(pDestDb, pClonedObj, idMap, Adesk::kFalse);

    if (*es != Acad::eOk) {

    pTsRecord->close();

    delete pTsIter;

    pTsTable->close();

    return;

    }

    *es = pTsRecord->close();

    if (*es != Acad::eOk) {

    delete pTsIter;

    pTsTable->close();

    return;

    }

    if (pClonedObj != NULL) {

    *es = pClonedObj->close();

    if (*es != Acad::eOk) {

    delete pTsIter;

    pTsTable->close();

    return;

    }

    }

    }

    delete pTsIter;

    *es = pTsTable->close();

    }

    }

    Образцы Подстановочных знаков в Списках Фильтра

    Названия{*имена*} Символа, указанные в списках фильтра могут включать образцы подстановочных знаков. Образцы подстановочных знаков, признанные acedSSGet () - тот же самый как признанные функцией acutWcMatch ().
    Следующий типовой код отыскивает анонимный блок, названный *U2.
    eb2.restype = 2; // Block name
    strcpy(sbuf1, "’*U2"); // Note the reverse quote.
    eb2.resval.rstring = sbuf1; // Anonymous block name
    eb2.rbnext = NULL;
    // Select Block Inserts of the anonymous block *U2.
    acedSSGet("X", NULL, NULL, &eb2, ssname1);

    Образование класса пользователя

    ObjectARX обеспечивает набор макрокоманд, объявленных в rxboiler.h файле, который помогает Вам создать новые классы, полученные из AcRxObject. Вы можете получать новые классы из большинства классов в ObjectARX иерархии кроме Выпуска AutoCAD 12 набора объектов (перечисленный в главе 6, “ примитивы, ”) и таблица идентификаторов классифицирует. Если Вы не используете макрокоманды ObjectARX, чтобы определить ваш новый класс, класс наследует тождество во время выполнения его наиболее непосредственного{*немедленного*} ObjectARX-зарегистрированного родительского класса.
    Приложения могут наиболее эффективно получать новые классы из следующих классов:
    § AcRxObject
    § AcRxService
    § AcDbObject
    § AcDbEntity
    § AcDbCurve
    § AcDbObjectReactor
    § AcDbDatabaseReactor
    § AcDbEntityReactor
    § AcTransactionReactor
    § AcEdJig
    § AcEditorReactor
    § Приложения не должны получить классы из следующего:
    § AcDbAttribute
    § AcDbAttributeDefinition
    § AcDbArc
    § AcDbBlockReference
    § AcDbCircle
    § AcDbFace
    § AcDbLine
    § AcDbMInsertBlock

    § AcDbPoint

    § AcDbShape

    § AcDbSolid

    § AcDbText

    § AcDbTrace

    § Все классы AcDbXxxDimension

    § AcDbViewport

    § AcDbGroup

    § Все классы, полученные из AcDbSymbolTable

    § Все классы, полученные из AcDbSymbolTableRecord

    § AcDbBlockBegin

  • AcDbBlockEnd


  • AcDbSequenceEnd


  • AcDb2dPolyline


  • AcDb2dPolylineVertex


  • AcDb3dPolyline


  • AcDb3dPolylineVertex


  • AcDbPolygonMesh


  • AcDbPolygonMeshVertex


  • AcDbPolyFaceMesh


  • AcDbPolyFaceMeshVertex


  • AcDbFaceRecord


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

    Общие функции Примитива

    Примитивы также имеют множество общих{*обычных*} функций, прежде всего предназначенных для использования в соответствии с AutoCAD. Этот раздел обеспечивает общий фон{*подготовку*} при использовании некоторых из этих функций. Для примеров осуществления функций для новых классов, см. главу 13, “ Происходящий от AcDbEntity. ”
    Общие{*обычные*} функции примитива включают следующее:
  • intersectWith () используется в вырезке, простираться, филе, chamfer, перерыве, и возражать поспешные операции Intersection

  • transformBy () используется, чтобы пройти в преобразованной матрице, которая перемещает, масштабирует, или вращает пункты{*точки*} в объекте

  • getTransformedCopy () создает копию объекта и применяет преобразование к этому

  • getOsnapPoints () возвращает поспешные пункты{*точки*} и вид поспешных пунктов{*точек*}

  • getGripPoints () возвращает пункты{*точки*} власти{*захвата*}, которые являются надмножеством пунктов{*точек*} протяжения

  • getStretchPoints () значения по умолчанию к getGripPoints () и обычно имеют то же самое выполнение

  • moveStretchPointsAt () используется командой STRETCH AutoCAD, чтобы переместить указанные пункты точки и значения по умолчанию к transformBy ()

  • moveGripPointsAt () используется редактированием власти{*захвата*} AutoCAD, чтобы переместить указанные точки и значения по умолчанию к transformBy ()

  • worldDraw () создает представление-независимое геометрическое представление примитива

  • viewportDraw () создает представление геометрического объекта иждивенца представления примитива

  • draw () стоит в очереди примитив и сбрасывает на диск графическую очередь так, чтобы примитив и что - нибудь еще в очереди были оттянуты

  • list() используется командой LIST AutoCAD и производит acutPrintf () инструкции

  • getGeomExtents () возвращает пункты{*точки*} угла поля, которое включает трехмерные степени вашего примитива

  • explode() расчленяет примитив в набор более простых элементов

  • getSubentPathsAtGsMarker () возвращает пути подпримитива, которые передают данному GS маркер (см. “ GS Маркеры и Подпримитивы ” на странице 109)

  • getGsMarkersAtSubentPath () возвращает GS маркер, который соответствует данному пути подпримитива

  • subentPtr () возвращает указатель, соответствующий данному пути подпримитива

  • highlight () высвечивает указанный подпримитив (см. “ GS Маркеры и Под-примитивы ” на странице 109)


  • Общие Шаги для Использования AcEdJig

    AcEdJig разработан{*предназначен*}, чтобы управлять перетащенной последовательностью, поставляя{*снабжая*} графической обратной связи, указанной типом курсора и одиночным объектом.
    Использовать AcEdJig класс
    1 Создают образец вашего полученного класса AcEdJig.
    2 Устанавливают ваш текст подсказки с AcEdJig:: setDispPrompt () функция.
    3 Звонят,  AcEdJig:: перетаскивают () функцию, которая управляет перетащенным циклом и в свою очередь вызывает{*называет*} дискретизатор (), модифицируйте (), и объект () функции, пока пользователь не заканчивает перетащенную последовательность.
    4 Проверка в пределах дискретизатора () функция:
    Если Вы используете подсказку с ключевыми словами, вызовите AcEdJig:: setKeywordList () функция.
    Если Вы хотите установить специальный тип курсора, назовите AcEdJig:: setSpecialCursorType () функцией (. Этот шаг необязательный и может типично опускаться.)
    Если желательно, ограничения места на перетащенную последовательность и возвращаемое значение, использующее AcEdJig:: setUserInputControls () функция.
    5 Проверяют{*отмечают*} состояние возвращения от AcEdJig::, перемещается{*перетаскивает*} () функцию и передает{*совершает*} изменения{*замены*} перетащенной последовательности. Если пользователь отменил или прервал процесс, исполнять соответствующую очистку.


    Общие Свойства Примитива

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

  • Linetype

  • Linetype масштаб

  • Видимость

  • Уровень

  • вес Строки

  • Графическое название{*имя*} стиля

  • Когда Вы добавляете примитив к блочному отчету{*записи*} таблицы, AutoCAD автоматически вызывает AcDbEntity:: setDatabaseDefaults () функция, которая устанавливает свойства в их значения по умолчанию, если Вы явно не установили их.
    AcDbViewport приобретает параметры настройки текущего графического окна.
    Если свойство было явно не определено для примитива, текущее значение базы данных для того свойства используется. См. главу 4, “ Операции Базы данных, ” для описания функций члена, используемых для установки и получения текущих значений свойства, связанных с базой данных.

    Общий Доступ

    Большинство генерала функций, которые обращаются К AutoCAD - acedCommand () и acedCmd (). Подобно функции (команды) в AutoLISP, эти функции посылают команды и другой ввод непосредственно к Приглашению ко вводу команды AutoCAD.
    Int
    AcedCommand (int rtype, ...);
    Int
    AcedCmd (struct resbuf *rbp);
    В отличие от большинства других функций взаимодействия AutoCAD, acedCommand () имеет список параметров переменной длины: параметры к acedCommand () обработаны как пары если бы не RTLE и RTLB, которые необходимы, чтобы передать точку указки. Первый из каждой пары параметра идентифицирует тип результата параметра, который следует, и второй содержит фактические данные. Заключительный параметр в списке - одиночный параметр, чей значение является или 0 или RTNONE. Как правило, первый параметр к acedCommand () - тип, закодируют RTSTR, и второй параметр данных - строка, которая является именем команды, чтобы вызвать. Следующие пары параметра определяют опции или данные, которых указанная команда требует.
    Коды типа в acedCommand () список параметров - типы результата.
    Параметры данных должны соответствовать типам данных и значениям, ожидаемым последовательностью подсказки той команды. Они могут быть строки, реальные значения, целые числа, точки, названия{*имена*} примитива, или названия{*имена*} набора выбора. Данные типа углов, расстояний, и точек можно пропускать или как строки (поскольку пользователь мог бы вводить их) или как значения непосредственно (то есть как целое число, реальное, или направлять значения).
    Пустая строка (“ ”) эквивалентна вводу пространства{*пробела*} на клавиатуре.
    Из-за идентификаторов типа, acedCommand () список параметров - не тот же самый как список параметров для AutoLISP подпрограмма (команды). Знайте это, если Вы преобразовываете подпрограмму AutoLISP в ObjectARX-приложение.
    Имеются ограничения на команды, которые acedCommand () может вызывать, которые являются сопоставимыми ограничениям на AutoLISP функция (команды).

    ОБРАТИТЕ ВНИМАНИЕ На acedCommand () и acedCmd () функции могут вызывать команду SAVE ИЛИ SAVEAS AutoCAD. Когда они делают так, AutoLISP выпускает kSaveMsg сообщение к всем другим ObjectARX-приложениям, в настоящее время загруженным, но не к приложению, которое вызвало SAVE. Сопоставимый код послан, когда эти функции вызывают NEW, OPEN, END, или QUIT от приложения.

    Следующая типовая функция показывает несколько, вызывает к acedCommand ().

    int docmd()

    {

    ads_point p1;

    ads_real rad;

    if (acedCommand(RTSTR, "circle", RTSTR, "0,0", RTSTR, "3,3", 0) != RTNORM)

    return BAD;

    if (acedCommand(RTSTR, "setvar", RTSTR, "thickness", RTSHORT, 1, 0) != RTNORM)

    return BAD;

    p1[X] = 1.0; p1[Y] = 1.0; p1[Z] = 3.0;

    rad = 4.5;

    if (acedCommand(RTSTR, "circle", RT3DPOINT, p1, RTREAL, rad, 0) != RTNORM)

    return BAD;

    return GOOD;

    }

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

    1 Рисует круг, который проходит до (3.0,3.0) и чей центр - в (0.0,0.0).

    2 Изменяют текущую толщину к 1.0. Обратите внимание, что первый запрос к acedCommand () передает точки как строки, в то время как секунда передает короткое целое число. Любой метод возможен.

    3 Рисует другой (вытесненный) круг, чей центр - в (1.0,1.0,3.0) и чей радиус - 4.5. Этот последний{*прошлый*} запрос к acedCommand () использует трехмерную точку и реальный (с двойной точностью с плавающей точкой) значение. Обратите внимание, что точки пропускает ссылка, потому что ads_point - тип массива.

    Оценка Внешних Функций

    Как только внешняя функция была определена, AutoLISP может вызывать это с запросом kInvkSubrMsg. Когда ObjectARX-приложение получает этот запрос, это отыскивает целочисленный код внешней функции,  вызывая acedGetFunCode (). Тогда инструкция выключателя, условный оператор, или таблица с  функциональным запросом могут выбирать и вызывать обозначенный функциональный обработчик. Это - функция, что ObjectARX-приложение определяет, чтобы осуществить внешнюю функцию. Обратите внимание, что имя обработчика и имени, определенного acedDefun () (и поэтому признанный AutoLISP) - не обязательно то же самое имя.
    Если функциональный обработчик ожидает параметры, это может отыскивать их значения,  вызывая acedGetArgs (), который возвращает указатель на список связей буферов результатов, которые содержат значения, прошел от AutoLISP. Если обработчик не ожидает никакие параметры, не требоваться вызвать acedGetArgs () (это может делать так так или иначе, проверять, что никак параметры не пропускали). Поскольку это отыскивает его параметры от списка связей, функциональный обработчик может также осуществлять списки параметров переменной длины или изменяющиеся типы параметра.
    ОБРАТИТЕ ВНИМАНИЕ, что  функциональный обработчик должен проверить номер, и тип параметров прошел к этому, потому что не имеется никакого способа сообщить AutoLISP, каковы требования.
    Функциональные обработчики, которые ожидают параметры, могут быть написаны так, чтобы они запросили пользователя относительно значений, если acedGetArgs () возвращает список параметров NULL. Эта методика часто применяется к внешним функциям, определенным как команды AutoCAD.
    Группа функций ObjectARX известный как функции возвращения значения (типа acedRetInt(), acedRetReal(), и acedRetPoint()) позволяет внешней функции возвратить значение выражению AutoLISP, которое вызвало это.
    Параметры, которые пропускают между внешними функциями и AutoLISP, должны оценить к одному из следующих типов: целое число, реальный (с плавающей точкой), строковый, точка (представленный в AutoLISP как список двух или трех реальных значений), имени примитива, имени набора выбора, символы AutoLISP t и nil, или список, который содержит предыдущие элементы. Символы AutoLISP к другие чем t и nil не пропускают или от внешних функций, но ObjectARX-приложения, могут отыскивать и устанавливать значение символов AutoLISP,  вызывая acedGetSym () и acedPutSym ().
    Если, например, внешняя функция в ObjectARX-приложении вызвана со строкой, целым числом, и реальным параметром, версия AutoLISP такой функции может быть представлена следующим образом:
    ( Doitagain pstr iarg rarg)
    Принимая, что функция была определена acedDefun(), пользователь AutoCAD может вызывать это со следующим выражением:
    Команда: (doitagain “ Стартовая ширина - ” 3 7.12)
    Этот запрос снабжает значениями для строки функции, целого числа, и вещественного числа
    Параметры, к которым doitagain () функциональный обработчик отыскивает запросом
    AcedGetArgs (). Для примера поиска параметров таким образом, см. первый пример в “ Списки и Другие Динамически Размещенные Данные ” на странице 546.

    Описатели Области просмотра

    Функция acedVports (), подобно функции AutoLISP (vports), получает список описателей текущих областей просмотра и их местоположений.
    Следующий типовой код получает текущую конфигурацию области просмотра и передает это назад к AutoLISP для дисплея.
    struct resbuf *rb;
    int rc;
    rc = acedVports(&rb);
    acedRetList(rb);
    acutRelRb(rb);
    Например, учитывая конфигурацию с  одиночной областью просмотра со включенным TILEMODE, предшествующий код может возвращать список, показанный в следующем рисунке.
    Описатели Области просмотра
    Точно так же, если четыре области просмотра равняться-размера расположены в четырех углах экрана, и TILEMODE включен, предшествующий код может возвращать конфигурацию, показанную в следующем рисунке.
    Описатели Области просмотра
    Описатель текущей области просмотра - всегда сначала в списке. В списке, показанном в предшествующем числе{*рисунке*}, номер 5 области просмотра - текущая область просмотра.

    Определение прокси-объекта

    Прокси-объект - объект AutoCAD, создает в памяти как держатель данных идентификатора объекта для заказного объекта ObjectARX. AutoCAD автоматически создает прокси-объекты, когда приложение, которое определяет объект, не загружено.
    Прокси-объекты созданы для объектов и примитивов. AutoCAD использует прокси-объекты, чтобы обеспечить доступ для чтения данных в заказном объекте, полученном из AcDbObject или AcDbEntity. Прокси-объекты также обеспечивают управляемые возможности редактирования этого данными. Родительское приложение определяет степень тех возможностей редактирования с параметром PROXY_FLAGS макрокоманды ACRX_DXF_DEFINE_MEMBERS.
    Класс прокси-объекта AcDbProxyObject получен из AcDbObject, и класс прокси-примитива AcDbProxyEntity получен из AcDbEntity. И - абстрактные классы, которые не могут быть действительны и включены в ObjectARX API.
    Прокси-объекты преобразовывают назад к первоначальному заказному объекту всякий раз, когда родительское приложение загружено. Например, если прокси-объекты созданы в начале сессии рисунка, и родительское приложение впоследствии загружено, прокси-объекты восстановлены к заказным объектам.
    При специальных обстоятельствах, прокси-объекты написаны к файлам, но прокси-объекты обычно существуют только в памяти.
    ObjectARX разработчики может затрагивать создание и управлять модификацию прокси-объектов,  используя макрокоманду ACRX_DXF_DEFINE_MEMBERS и требование, загружающее особенности в AutoCAD (см. “ Загрузка по требованию ” на странице 45). Кроме того, они могут использовать функции классов прокси-объекта в их собственных приложениях, чтобы управлять прокси-объектами, которые AutoCAD создает для заказных объектов других приложений.

    Определение Внешних Функций

    Когда ObjectARX-приложение получает запрос kLoadDwgMsg от AutoCAD, это должно определить все его внешние функции,  вызывая acedDefun () однажды для каждой функции. AcedDefun () запрос связывает имя внешней функции (прошел как строковое значение) с целочисленным кодом, который является уникальным в пределах приложения. Целочисленный код не должен быть отрицателен, и это не может быть большее чем 32,767 (другими словами, код - короткое целое число).
    Следующий запрос к acedDefun () определяет, что AutoLISP признает, что внешняя функция вызвала doit в AutoLISP, и что, когда AutoLISP вызывает doit, это передает функциональный нуль кода (0) к ObjectARX-приложению:
    AcedDefun ("doit", 0);
    Строка, которая определяет имя новой внешней функции, может быть любое имеющее силу имя символа AutoLISP. AutoLISP преобразовывает это к всему верхнему регистру и сохраняет это как символ типа Exsubr.
    Внешние функции определены отдельно для каждого открытого документа в MDI. Функция определяется, когда документ становится активным. Для подробной информации, см. главу 16, “ Многодокументная среда. ”
    ПРЕДУПРЕЖДЕНИЕ! Если два или больше ObjectARX-приложения определяют функции (в том же самом документе) которые имеют то же самое имя, AutoLISP признает только наиболее недавно определенную внешнюю функцию. Предварительно загруженная функция будет потеряна.
    Это может также случаться, если пользователь вызывает defun с противоречивым именем.
    Как в AutoLISP, новая функция может быть определена как команда AutoCAD приписыванием ее имя с “ C: ” или “ c: ”, как показано в следующем примере:
    AcedDefun ("C:DOIT", 0);
    В этом случае, DOIT может теперь быть вызван от Приглашения ко вводу команды AutoCAD без того, чтобы включить его имя в круглых скобках.
    Функции, определенные как команды AutoCAD могут все еще быть вызваны от выражений AutoLISP, при условии, что “ C: ” префикс включен как часть их названий.
    Например, учитывая предыдущий acedDefun () запрос, пользователь AutoCAD мог также вызывать команду DOIT как функция с параметрами:
    Команда: (c:doit x y)
    ПРЕДУПРЕЖДЕНИЕ! Если приложение определяет команду C:XXX, чей конфликты имен со встроенной командой или именем команды, определенным в acad.pgp файле, AutoCAD не признает внешнюю функцию как команда. Функция может все еще вызываться как AutoLISP внешняя функция. Например, после запроса acedDefun ("c:cp", 0), ввод пользователя cp (псевдоним для COPY, определенного в acad.pgp) вызывает команду COPY AutoCAD, но пользователь мог вызывать внешнюю функцию с c:cp.
    ОБРАТИТЕ ВНИМАНИЕ Имена функции, определенные acedDefun () могут быть неопределены,  вызывая acedUndef (). После того, как функция была неопределена, попытка вызывать это вызывает ошибку.

    Определения Функции Повторного вызова

    Чтобы регистрировать функции повторного вызова с ads_action_tile () и ads_new_dialog (), adsdlg.h определяет тип CLIENTFUNC, который указывает на функцию повторного вызова как показано в следующей примере:
    typedef void (*CLIENTFUNC)(ads_callback_packet *cpkt);
     
    (Пустой) символ CALLB определен, чтобы делать функции повторного вызова проще, чтобы расположить в исходном тексте, как в следующем примере:
    static void CALLB
    dbox_handler(ads_callback_packet *cpkt)
    Вы можете использовать ads_new_dialog () функция также, чтобы определить заданную по умолчанию функцию повторного вызова для диалогового окна. Если Вы не используете эту особенность, передаете нулевой{*пустой*} указатель функции NULLCB, который определен следующим образом:
     #define NULLCB ((CLIENTFUNC) 0)

    Определенные Примитивы

    Примитив в базе данных имеет графическое представление. Примеры примитивов включают строки, круги, дуги, текст, solids, области{*регионы*}, сплайны, и эллипсы. AcDbEntity класс получен из AcDbObject.
    С несколькими исключениями, примитивы содержат всю необходимую информацию относительно их геометрии. Несколько примитивов содержат другие объекты, которые проводят{*держат*} их геометрическую информацию или атрибуты. Сложные примитивы включают следующее:
  • AcDb2dPolyline, который имеет объекты AcDb2dPolylineVertex

  • AcDb3dPolyline, который имеет объекты AcDb3dPolylineVertex

  • AcDbPolygonMesh, который имеет объекты AcDbPolygonMeshVertex

  • AcDbPolyFaceMesh, который имеет объекты AcDbPolyFaceMeshVertex и объекты AcDbFaceRecord

  • AcDbBlockReference, который имеет объекты AcDbAttribute

  • AcDbMInsertBlock, который имеет объекты AcDbAttribute

  • Примеры создания и выполнения итераций через сложные примитивы обеспечиваются в “ Сложные Примитивы ” на странице 134.

    Options

    Представляет связанные разработчиком опции приложения ARX.
    Options (Group/CLasses/Services): Enter an option
    ·
     Group
    Перемещает указанную группу команд, зарегистрированных от приложений ARX, чтобы быть первой группой, обысканной при решении названий{*имен*} команд AutoCAD. Другие зарегистрированные группы, если имеется любой, впоследствии обысканы, в том же самом заказе{*порядке*}, как прежде, чем команда ARX была выполнена.
    Command Group Name: Enter the command group name
    Заказ{*порядок*} поиска важен только, когда название{*имя*} команды перечислено в множественных группах. Этот механизм позволяет различным приложениям ARX определять те же самые названия{*имена*} команды в их собственных отдельных группах команд.
    ARX
    приложения, которые определяют группы, команд должны издать название{*имя*} группы в их документации.
    Группа не предназначена, чтобы быть выбранной пользователем непосредственно. Пользователь определяет, которая группа обыскана сначала,  взаимодействуя со сценарием, который выполняет команду ARX
    с опцией Group. Эта возможность обычно внедряется в ключевые сценарии пункта меню. Пользователь выбирает пункт меню от сценария.
    Ключевой сценарий пункта меню выполняет опцию Group, чтобы установить, которая группа обыскана сначала, давая команды того же самого названия{*имени*} (но вероятно различные функциональные возможности) от одного прикладного старшинства по командам от другого.
    Например, приложения по имени ABC и XYZ Интерьеры определяют группы ABC команд и XYZ, соответственно. Большинство команд Конструкции ABC названо с терминологией конструкции, в то время как большинство XYZ команды Интерьеров названо со внутренней областью, украшающей терминологию, но и приложения определяют команды по имени INVENTORY и ORDERS. При работе над аспектами конструкции рисунка, пользователь выбирает пункт меню, определенный Конструкцией ABC, и следующий сценарий выполняется:
    ARX
    Группа
    ABC
    Сценарий выталкивает набор команд Construction ABC, чтобы дать этому высший приоритет и решать INVENTORY к версии Конструкции ABC команды. Позже, когда внутренний проектировщик работает над рисунком к тому же самому набору загруженных приложений, выбор,  ключевой значок гарантирует, что XYZ команды Интерьеров имеют старшинство.
    ОБРАТИТЕ ВНИМАНИЕ, что группы Command не связаны с командами, определенными в AutoLISP или определены запросом к acedDefun () Приложениями ObjectArx. Программный механизм, который определяет группы команд,  описан в “ Заказ{*порядок*} Поиска ” на странице 42.
  • Classes

  • Отображает иерархию классов классов C++, полученных из объектов{*целей*}, зарегистрированных в системе, ли зарегистрированный в соответствии с AutoCAD или в соответствии с программой ARX.
  • Services

  • Перечисляет названия{*имена*} всех услуг, зарегистрированных в соответствии с AutoCAD и в соответствии с загруженными программами ARX.

    Основная операция средства просмотра

    Следующее - основные шаги, чтобы установить вид (или виды) рисунка, сопровождаемого в соответствии с описанием графического выбора примитива.
    Устанавливать вид
    1 приложение ObjectDBX загружает DWG
    файл в образец AcDbDatabase.
    2 приложение создает область просмотра и передает связанный AcGiViewport к AcGix.
    3 приложение сообщает AcGix инициализировать перегенеральный из определенной записи таблицы блоков или отдельного примитива в данный набор областей просмотра.
    4 AcGix восстанавливает примитив (ы) во все активные области просмотра. По существу, каждый примитив открыт для чтения, его AcDbEntity:: worldDraw () вызван, и если состояние возвращения указывает, его AcDbEntity:: viewportDraw () перегрузка члена вызвана однажды для каждой активной области просмотра.
    5 От любого из этих членов, каждый класс свободен получить объекты AcGiWorld/ViewportGeometry и объекты AcGiSubentityTraits, и делать, вызывает, чтобы послать геометрические графические и графические черты (атрибуты подобно цвету, linetype, шрифт) к ним. Эти объекты AcGi
    осуществлены в AcGix, который берет “входные” геометрические примитивы и черты и обрабатывает их, сокращая их к примитивам прошел в к образцу AcGixVectorTaker, связанного с каждой активной областью просмотра.
    6 vectortaker берет входные пакеты сообщения (или функция вызывает) и преобразовывает их в, вызывает к основной системе графики.

    Основы глубокого клонирования

    Глубокие функции клона копируют объект и его ссылки монопольного использования. Любые ссылки указателя игнорируются. Копируют функции клона wblock жесткие владельцы и жесткие указатели и игнорируют мягкие ссылки. В дополнение к копированию этой иерархии находящихся в собственности объектов, и глубокие функции клона и функции клона wblock также обрабатывают ссылки клонированного объекта, трансляция ссылок, чтобы указать на новые объекты в случае необходимости.
    Чтобы инициализировать операцию имитации, используйте одну из следующих функций:
    AcDbDatabase:: deepCloneObjects ()
    AcDbDatabase:: wblock ()
    AcDbDatabase:: insert()
    AcDbDatabase:: deepCloneObjects () только поддерживает клонирование в пределах единственной{*отдельной*} базы данных. Если Вы должны клонировать объекты между базами данных, использовать или wblock (), вставьте (), или комбинация,  и (типа wblock () к временной базе данных, и затем вставьте () что базу данных в существующую базу данных адресата).
    При использовании AcDbDatabase:: вставка (), только вставляют к базам данных адресата, которые уже были сформированы. Вы можете получить полностью сформированный (и возможно полностью заполняемый) базу данных адресата,  используя текущий рисунок, чтобы формировать новую базу данных с параметром конструктора Adesk:: kTrue или,  создавая пустую новую базу данных, используя параметр конструктора Adesk:: kFalse и затем вызывая AcDbDatabase:: readDwgFile () на этом, чтобы заполнить это.
    Вообще, чтобы использовать AcDbDatabase:: deepCloneObjects (), AcDbDatabase:: wblock (), или AcDbDatabase:: вставка () функции в вашем коде, Вы не должны знать того, как карта объекта ID заполнена или точно, что случается в течение каждой стадии глубокого клонирования. Если Вы создаете новый класс, и Вы хотите перегрузить AcDbObject:: deepClone () или AcDbObject:: wblockClone () функции, вы будете должны быть знакомыми с подробностями тех функций, которые описаны в “ Реализация deepClone () для Классов пользователя ” на странице 476.
    AcDbObject:: deepClone () и AcDbObject:: wblockClone () функции не должен быть вызван{*назван*} непосредственно на заказном объекте в прикладном коде. Они только вызваны как часть цепочки от операции клонирования более высокого уровня.

    Осуществление Точки входа для AutoCAD

    AutoCAD звонит в ObjectARX модуль через acrxEntryPoint (), который заменяет main()  программы C++. Вы ответственны за осуществление acrxEntryPoint (), как описано в этом разделе.
    AcrxEntryPoint () функция служит как точка входа для AutoCAD,  чтобы связаться с приложением ObjectARX. ObjectARX программы может связываться с AutoCAD,  возвращая коды состояния. Все запросы, чтобы вызвать функции, определенные через acedDefun() сделаны с acrxEntryPoint(). Если Вы определяете новую команду с
    ObjectARX или с acedRegFunc(), AutoCAD немедленно выполняет функцию, связанную с командой (см. “ Загрузка ObjectARX Приложение ” на странице 43).
    AcrxEntryPoint () функция имеет следующую сигнатуру:
    extern "C"
    AcRx::AppRetCode
    acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt);

    msg
    Представляет сообщение, посланное от ObjectARX ядра К приложению.
    pkt
    Содержит значения данных пакета.
    AppRetCode
    Содержит код состояния, возвращенный AutoCAD.

    В пределах определения acrxEntryPoint(), Вы записываете выключатель Операторный или подобный код, чтобы декодировать сообщения от AutoCAD, исполнить Соответствующие действия, связанные с каждым сообщением, и возвращением целочисленное состояние.
    ПРЕДУПРЕЖДЕНИЕ! Использование kRetError для конечного возвращаемого значения от AcrxEntryPoint() заставит ваше приложение быть разгруженным, кроме Для сообщений kOleUnloadAppMsg и kUnloadAppMsg. В этих случаях, если KRetError возвращен, приложение не будет разгружено.
    Следующий код показывает скелет допустимой инструкции выключателя:
    AcRx::AppRetCode
    acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt)
    {
    switch(msg) {
    case AcRx::kInitAppMsg:
    break;
    case AcRx::kUnloadAppMsg:
    break;
    ...
    default:
    break;
    }
    return AcRx::kRetOK;
    }

    От сети нитей к сети объектов

    Сеть traversers представляет списки смежных вершин объектов сети, которые связаны в контексте объекта сети более высокий измерение.
    Сеть traversers

    Class
    Objects
    AcBrMesh2dElement2dTraverser
    AcBrMesh2d (owner)
    AcBrElement2d (position)
    AcBrElement2dNodeTraverser
    AcBrElement2d (owner)
    AcBrNode (position)

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

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


    От Топологического Traversers до Объектов

    Traversers  - пересечение, обход, кромка
    Топологический traversers представляют списки смежных вершин топологических объектов, которые связаны в контексте топологического объекта с  более высоким измерением.
    Каждый специфический тип traverser выставляет, и объект, который это использует для контекста (то есть владелец списка смежных вершин) и объект, на который это в настоящее время указывает (то есть позиция списка смежных вершин) с функциями set* и get*.
    Топологический traversers

    Class
    Objects
    AcBrBrepComplexTraverser
    AcBrBrep (owner)
    AcBrComplex (position)
    AcBrBrepShellTraverser
    AcBrBrep (owner)
    AcBrShell (position)
    AcBrBrepFaceTraverser
    AcBrBrep (owner)
    AcBrFace (position)
    AcBrBrepEdgeTraverser
    AcBrBrep (owner)
    AcBrEdge (position)
    AcBrBrepVertexTraverser
    AcBrBrep (owner)
    AcBrVertex (position)
    AcBrShellFaceTraverser
    AcBrShell (owner) 
    AcBrFace (position)
    AcBrFaceLoopTraverser
    AcBrFace (owner) 
    AcBrLoop (position)
    AcBrLoopEdgeTraverser
    AcBrLoop (owner) 
    AcBrEdge (position)
    AcBrLoopVertexTraverser
    AcBrLoop (owner) 
    AcBrVertex (position)
    AcBrVertexLoopTraverser
    AcBrVertex (owner) 
    AcBrLoop (position)
    AcBrVertexEdgeTraverser
    AcBrVertex (owner)
    AcBrEdge (position)
    AcBrEdgeLoopTraverser
    AcBrEdge (owner) 
    AcBrLoop (position)


    Вершина для граней
    Край может иметь в большинстве двух вершины. Они выставлены явными функциями в AcBrEdge классе (см. следующий раздел), поскольку traverser был бы расточителен для такой тривиальной смежности.
    Вершина для циклов
    Цикл может иметь много вершины, но может иметь только один (в случае единственного края, или в случае особенности, где не имеется никакой геометрии края, типа вершины конуса). LoopVertex обход охватывает оба общий список границ вершины на лице также как особенностях. Этот список может быть более экономический чем формирование дампа граней на цикле, если единственная вещь, представляющая интерес - геометрия точки для границы лица.
    EdgeLoop обход
    Этот класс определяет функции, которые связаны с радиальным упорядочением лиц, которые совместно используют общий край. Чтобы обеспечивать самую плотную связь к обходам списка края (AcBrLoopEdgeTraverser), лицо представлено его границей цикла в общедоступном крае. SetEdgeAndLoop () функция устанавливает владельца края и исходную позицию цикла. SetEdge () функция устанавливает владельца края и исходную позицию цикла. Позиция цикла не может быть установлена отдельно от края, поскольку радиальные обходы должны быть с сильной связью с лицо-контекстными списками края (то есть AcBrLoopEdgeTraverser).
    VertexLoop обход
    Этот класс определяет функции, которые связаны с радиальным упорядочением лиц, которые совместно используют общую вершину. Чтобы обеспечивать самую плотную связь к обходам списка края (AcBrLoopEdgeTraverser), лицо представлено его границей цикла в общедоступной вершине. SetVertexAndLoop () функция устанавливает владельца вершины и исходную позицию цикла. SetVertex () функция устанавливает владельца вершины и устанавливает исходную позицию цикла. Позиция цикла не может быть установлена отдельно от вершины, поскольку радиальные обходы должны быть с сильной связью с лицо-контекстными списками вершины (то есть AcBrLoopVertexTraverser).


    Отключение переключения документа

    Команды, которые имеют длинные процессы вычисления и опрос для cancelation,  восприимчивы к наличию событий пользователя, или внешние запросы ActiveX
    входят и вызывают проблемы с их внутренним состоянием, если они изменяют{*заменяют*} документы.
    Поэтому, некоторые команды отключат переключение документа в течение их стадии обработки. Имеется список команд, включенных В AutoCAD или снабженный связанными ObjectARX-приложениями, которые отключают переключение документа при обработке:
    § PLOT
    § REGEN
    § RENDER
    § HIDE
    § SHADE
    Следующие команды отключают переключение документа повсюду их обращения:
    § NEW
    § OPEN
    § TABLET
    Кроме того, AcApDocManager::disableDocumentActivation() и AcApDocManager::enableDocumentActivation() отключит и будет вновь давать возможность активации документа. Прототипы для этих методов:
    virtual Acad::ErrorStatus
    disableDocumentActivation() = 0;
    virtual Acad::ErrorStatus
    enableDocumentActivation() = 0;
    Следующая функция указывает, позволяется ли активация документа:
    virtual bool
    isDocumentActivationEnabled() = 0;

    Открытие и Закрытие объекта ObjectARX

    Все примеры кода, показанные в этой главе иллюстрируют протокол для открытия и закрытия объектов, который вы будете должны соблюсти всякий раз, когда Вы работаете с объектами резидента-базы. Этот протокол гарантирует, что объекты - физически в памяти, когда к ним должны обращаться.Прежде, чем Вы можете изменять объект, Вы должны открыть его:
    acdbOpenObject(pObject, objId, AcDb::kForWrite);
    Открытые функции имеют параметр режима, который определяет, открываете ли Вы объект для чтения, записи или уведомления. В то время как объект открыт для записи, Вы можете изменять его. Когда Вы закончите, Вы должны явно закрыть объект как показано в следующем примере, независимо от режима, в котором это было открыто:
    pObject->close();
    Следующее - типовой код для изменения цвета объекта:
    Acad::ErrorStatus
    changeColor(AcDbObjectId entId, Adesk::UInt16 newColor)
    {
    AcDbEntity *pEntity;
    acdbOpenObject(pEntity, entId,AcDb::kForWrite);
    pEntity->setColorIndex(newColor);
    pEntity->close();
    return Acad::eOk;
    }
    ПРЕДУПРЕЖДЕНИЕ! Непосредственно удаление объекта, который был добавлен к базе, заставляет AutoCAD грохаться.

    Открытие и Закрытие Объектов Базы данных

    Каждый объект AcDbObject может быть упомянут тремя различными способами:
  • его маркером{*дескриптором*}

  • его объектом ID

  • указателем образца C++

  • Когда AutoCAD не выполняется, рисунок сохранен в файловой системе.
    Объекты, содержащиеся в DWG файле идентифицированы их маркерами{*дескрипторами*}.
    После того, как рисунок открыт, информация рисунка доступна через объект AcDbDatabase. Каждый объект в базе данных имеет объект ID, который сохраняется в течение текущего сеанса редактирования, от создания до стирания AcDbDatabase, в котором объект постоянно находится. Открытые функции берут объект ID как параметр и возвращают указатель на объект AcDbObject. Этот указатель правилен, пока объект не закрыт, как показано в следующем рисунке.
    Открытие и Закрытие Объектов Базы данных
    Вы можете открывать объект, используя acdbOpenObject ():
    Acad::ErrorStatus
    AcDbDatabase::acdbOpenObject(AcDbObject*& obj,
    AcDbObjectId id,
    AcDb::OpenMode mode,
    Adesk::Boolean
    openErasedObject =
    Adesk::kFalse);
    Вы можете отображать маркер(дескриптор) к объекту ID, используя эту функцию:
    Acad::ErrorStatus
    getAcDbObjectId(AcDbObjectId& retId,
    Adesk::Boolean createIfNotFound,
    const AcDbHandle& objHandle,
    Adesk::UInt32 xRefId=0);
    Вы можете также открывать объект и затем запрашивать его маркер(дескриптор):
    AcDbObject* pObject;
    AcDbHandle handle;
    pObject->getAcDbHandle(handle);
    ОБРАТИТЕ ВНИМАНИЕ Всякий раз, когда объект базы данных открыт, это должно быть закрыто в самой ранней возможной возможности. Вы можете использовать AcDbObject:: близко () функция, чтобы закрыть объект базы данных.
    Ads_name эквивалентен
    AcDbObjectId. AcDb библиотека обеспечивает две автономных функции, которые позволяют Вам транслировать между AcDbObjectId и ads_name:
    // Returns an ads_name for a given object ID.
    //
    acdbGetAdsName(ads_name& objName,
    AcDbObjectId objId);
    // Returns an object ID for a given ads_name.
    //
    acdbGetObjectId(AcDbObjectId& objId,

    ads_name objName);

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

    AcDbEntity*

    selectEntity(AcDbObjectId& eId, AcDb::OpenMode openMode)

    {

    ads_name en;

    ads_point pt;

    acedEntSel("\nSelect an entity: ", en, pt);

    // Exchange the ads_name for an object ID.

    //

    acdbGetObjectId(eId, en);

    AcDbEntity * pEnt;

    acdbOpenObject(pEnt, eId, openMode);

    return pEnt;

    }

    Вы можете открывать объект в одном из трех режимов:

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


  • kForWrite. Объект может быть открыт для записи, если это не уже открыто. Иначе, открытые сбои.


  • kForNotify. Объект может быть открыт для уведомления, когда объект закрыт, открытым для чтения, или открытый для записи, но не, когда это уже открыто для, уведомляют. См. главу 15, “Уведомление”. Приложения будут редко должны открыться,  объект для уведомляет и посылает этому уведомление.


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



    Открытие объектов в различных режимах

    Object already opened for:

    kForRead

    kForWrite

    kForNotify

    openedForRead

    eAtMaxReaders

    (if readCount = 256;

    otherwise succeeds)

    eWasOpenForRead

    (Succeeds)

    openedForWrite

    eWasOpenForWrite

    eWasOpenForWrite

    (Succeeds)

    openedForNotify

    eWasOpenForNotify

    eWasOpenForNotify

    eWasOpenForNotify

    wasNotifying

    (Succeeds)

    eWasNotifying

    eWasNotifying

    Undo

    eWasOpenForUndo

    eWasOpenForUndo

    (Succeeds)

    Если Вы пробуете открывать объект для записи, и Вы получаете ошибку eWasOpenForRead, Вы можете использовать upgradeOpen () чтобы модернизировать открытого состояния, чтобы записать, если имеется только одно устройство считывания объекта. Тогда Вы использовали бы downgradeOpen () чтобы понизить его состояние, чтобы читать. Точно так же, если ваш объект открытый для, уведомляют — например, когда Вы получаете уведомление —, и Вы хотите открыть это для записи, Вы можете использовать upgradeFromNotify () чтобы модернизировать его открытого состояния, чтобы записать. Тогда Вы использовали бы downgradeToNotify () чтобы понизить его состояние, чтобы уведомить.

    Для получения дополнительной информации относительно того, как управлять комплексными последовательностями открытия и закрытия объектов, см. “ Менеджер Транзакции ” на странице 451.

    Отладка Приложений ObjectArx с Динамический MFC

    При отладке Приложений ObjectArx, сформированных с динамически связанной MFC
    библиотекой, свяжите с выпускаемой версией C время выполнения и MFC библиотеки.
    Это позволяет использование MFC или C
    отладку время выполнения средств, но не позволяет шагать в Microsoft MFC
    отлаживающий исходный текст.

    Отношения между AcDbObjects и Объектами Автоматизации

    AutoCAD осуществляет его модель объекта ActiveX Automation,  создавая связь между объектом резидента базы (AcDbObject) и объектом COM, который представляет это. Эта связь составлена из с двух одним направленным указателей. Первый указатель - IUNKNOWN объекта COM, который сохранен, используя переходный реактор на AcDbObject. Второй указатель - AcDbObjectId объекта резидента базы, который сохранен как поле на объекте COM.
    Отношения между AcDbObjects и Объектами Автоматизации
    Эта связь позволяет Вам отыскивать существующий указатель IUnknown данного объекта COM указатель AcDbObject, как показано в следующем коде:
    AcAxOleLinkManager* pOleLinkManager = AcAxGetOleLinkManager();
    // pObject is an AcDbObject*
    //
    IUnknown* pUnk = pOleLinkManager->GetIUnknown(pObject);
    // NOTE: AcAxOleLinkManager::GetIUnknown() does not AddRef()
    // the IUnknown pointer.
    Наоборот, Вы можете отыскивать AcDbObjectId объекта резидента базы,  представляемого данным объектом COM указатель IUnknown, как показано в следующем коде:
    IAcadBaseObject* pAcadBaseObject = NULL;
    // pUnk is the IUnknown* of a COM object representing
    // some object in the database
    //
    HRESULT hr = pUnk->QueryInterface(IID_IAcadBaseObject, (LPVOID*) &pAcadBaseObject);
    AcDbObjectId objId;
    if(SUCCEEDED(hr))
    {
    pAcadBaseObject->GetObjectId(&objId);
    }

    Относительные Испытания

    Если Вы не определяете иначе, имеется подразумеваемый ", “равняется" испытанию между примитивом и каждым элементом{*пунктом*} в списке фильтра. Для числовых групп (целые числа, реальные значения, точки, и векторы), Вы можете определить другие отношения включением относительных операторов в списке фильтра. Относительные операторы пропускают как специальные -4 группа, чей значение - строка, которая указывает испытание, которое нужно применить к следующей группе в списке фильтра.
    Следующий типовой код выбирает все круги, чей радиус больший чем или равняются 2.0:

    eb3.restype = 40; // Radius
    eb3.resval.rreal = 2.0;
    eb3.rbnext = NULL;
    eb2.restype = -4; // Filter operator
    strcpy(sbuf1, ">=");
    eb2.resval.rstring = sbuf1; // Greater than or equals
    eb2.rbnext = &eb3;
    eb1.restype = 0; // Entity type
    strcpy(sbuf2, "CIRCLE");
    eb1.resval.rstring = sbuf2; // Circle
    eb1.rbnext = &eb2;
    // Select circles whose radius is >= 2.0.
    acedSSGet("X", NULL, NULL, &eb1, ssname1);

    Ответ на Сообщения AutoCAD

    Имеются четыре категории сообщений, что AutoCAD посылает приложениям ObjectARX:
    · Сообщения, которые посланы всем приложениям
    · Сообщения, которые посланы только если  приложение имеет зарегистрированную  Alisp-функцию с acedDefun()
    · Сообщения, которые посланы приложениям, которые зарегистрированы как сервисы  ObjectARX
    · Сообщения, отвечающие приложениям, которые используют ActiveX Автоматизацию
    Следующие пять таблиц описывают сообщения, что AutoCAD посылает toObjectARX приложению. Первая таблица перечисляет сообщения, посланные всем приложениям.
    Сообщения, посланные всем приложениям Message

    Сообщение
    Описание
    KInitAppMsg
    Посланный, когда приложение ObjectARX загружено, чтобы открыть связь между AutoCAD и приложением.
    KUnloadAppMsg
    Посланный, когда приложение ObjectARX разгруженно (или когда пользователь разгружает приложение или когда сам AutoCAD закончен). Закрывает файлы и исполняет операции очистки.
    KLoadDwgMsg
    Посланным однажды, когда рисунок открыт. Тогда, если приложение регистрируется, любые функции с Автошепелявят, AutoCAD посылает это сообщение однажды за каждый рисунок, загруженный в редактора. Редактор AutoCAD полностью инициализирован в этом точке, и все глобальные функции доступны. Однако, Вы не можете использовать acedCommand () функция от kLoadDwgMsg
    KPreQuitMsgSent,
    когда AutoCAD выходит, но прежде, чем это начинает разгружать все приложения ObjectARX..

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

    Сообщение
    Описание
    kUnloadDwgMsg
    Посланный, когда пользователь выходит из сеанса рисунка.
    kInvkSubrMsg
    Посланным, чтобы вызвать функции буферизованное использование acedDefun ().
    kEendMsg
    Посланным только, когда команда END введена и имеются изменения(замены), которые должны быть сохранены (когда dbmod! = 0). KEndMsg не послан для НОВОГО или ОТКРЫТОГО, вместо этого, kSaveMsg и kLoadDwgMsg посланы. В течение КОНЦА, если dbmod = 0, то kQuitMsg послан вместо kEndMsg.
    kQuitMsg
    когда выход из AutoCAD (заканчивается без того, чтобы сохранить рисунок потому что QUIT команда была введена. KQuitMsg может также быть получен с командой END, как отмечено выше.
    Если команда END послана и dbmod = 0, то kQuitMsg послан.
    kSaveMsg
    когда AutoCAD сохраняет рисунок потому что SAVE
    SAVEAS, NEW или команда OPEN введены.
    kCcfgMsgSent
    когда AutoCAD возвращается от программы конфигурации, и используемый только для изменения драйвера дисплея.
    <
    Следующая таблица перечисляет сообщения, что приложение получает, если это имеет зарегистрированный сервис с ObjectARX.

    Сообщение
    Описание
    KDependencyMsg
    когда приложение ObjectARX имеет буферизованный объект AcRxService и индекс зависимости на тех сервисных изменениях от 0 до 1.
    KNoDependencyMsgSent
    когда приложение ObjectARX имеет буферизованный объект AcRxService и индекс зависимости на тех сервисных изменениях от 1 до 0.

    Следующая таблица перечисляет сообщения, что приложение должно ответить к тому, если это использует ActiveX Автоматизацию. См. главу 23, “ ОБЩАЯ ОБЪЕКТНАЯ МОДЕЛЬ, ActiveX Автоматизация, и Объектный Менеджер Свойства. ”

    Сообщение
    Описание
    kOleUnloadAppMsg
    Посылается, чтобы определить, может ли приложение быть выгружено (то есть ни один из его объектов ActiveX или интерфейсов не упомянут другими приложениями).

    См. rxdefs.h файл, где эти константы перечисления определены в соответствии с объявлением типа AppMsgCode. Вы будете должны решить, на которые сообщения ваше приложение ObjectARX ответит.
    Следующая таблица описывает рекомендуемые действия после получения данного сообщения. ObjectARX прикладные реакции на сообщения AutoCAD

    Сообщение
    Рекомендуемые действия
    kInitAppMsg
    Регистрируйте услуги, классы, AcEd команды и реакторы,  AcRxDynamicLinker реакторы. Инициализируйте системные ресурсы приложения типа устройств и окон.
    Исполните всю одноразовую раннюю инициализацию.
    AcRx, AcEd, и AcGe весь активен. Сохраните значение pkt параметра, если Вы хотите разблокировать и повторно блокировать ваше приложение. Не ожидайте, что драйверы устройства будут инициализированы, любые ресурсы интерфейса пользователя быть активными, приложения, которые будут загружены в специфическом порядке, будут автошепелявить, чтобы присутствовать, или любые базы данных, чтобы быть открытыми. Запросы, возводящие в степень любое из этих предположений приведут к состоянию ошибки, иногда фатальному.
    AcDb и AcGi библиотеки вообще еще не активен, хотя связано AcRx, и другие структуры на месте
    KUnloadAppMsg
    Исполняют заключительную системную очистку ресурса. Что-нибудь начатое или созданное в kInitAppMsg должно теперь быть остановлено или разрушено. Не ожидайте вещи быть любой отличным от описания kInitAppMsg. AutoCAD мог быть главным образом демонтирован к времени, этот запрос сделан, если бы не перечисленные библиотеки, поскольку активный в kInitAppMsg Делают описание.
    KOleUnloadAppMsg
    Это сообщение нужно ответить только приложениями, использующими ActiveX Автоматизацию.
    Ответьте с AcRx:: kRetOK, если приложение может быть вызгружено (ни один из его объектов ActiveX или интерфейсов не упомянут другими приложениями). Если это не может быть выгружено, отвечать с AcRx:: kRetError.
    KLoadDwgMsg
    исполняют инициализацию, уместную текущему рисунку сеанса редактирования. AcDb, AcGi, и интерфейс пользователя API - все теперь активные.
    Было ли что - нибудь сделано к рисунку, не определен.
    Все Снабженные автохамом API теперь активны. Вы можете исполнять регистрацию функции AutoLISP в это время, и инициализировать интерфейс пользователя. Другие операции, чтобы исполнить теперь включают поллинг драйверы AutoCAD и запрос AcEditorReactor события, если Вы хотите самый ранний возможный доступ к acdbHostApplicationServices()->workingDatabase().
    Не Делайте что - нибудь, что Вы не хотели бы случиться для каждого рисунка сеанс редактирования. Предположите, что это сообщение послано больше чем однажды в выполнение программы.
    KUnloadDwgMsg
    выпускают или очищают все начатое или буферизованный в ответ на код kLoadDwgMsg. Выпустите все AcDb реакторы, исключая постоянные реакторы.
    Не выпустите системные ресурсы, которые не связаны к сеансу редактирования, или очищают классы AcRx, AcEd реакторы, или команды; они остаются правильными(допустимыми) поперек сеансов редактирования.
    KDependencyMsg
    исполняют любые действия, которые являются необходимыми для вашего приложения, когда другие приложения станут зависящий от этого, типа блокировки вашего приложения так, чтобы это не могло быть разгруженно.
    KNoDependencyMsg
    исполняют любые действия, которые являются необходимыми для вашего приложения, когда имеются больше не никакие другие приложения, зависящие вашего, типа разблокирования вашего приложения так, чтобы это могло быть разгруженно пользователем если желательно.
    KInvkSubrMsg
    вызывают функции, буферизованные с acedDefun (). Определите функцию,  звоня по телефону к acedGetFuncode (). Возвращаемые значения с acedRetxxx ().
    Не Делайте много здесь кроме функционального обращения.
    KPreQuitMsg
    разгружают любые зависимости (приложения, DLLs, и так далее) который ваше приложение управляет, чтобы гарантировать, что они являются разгруженным before your приложением.
    kEndMsg
    kCfgMsg
    kQuitMsg
    kSaveMsg
    Рассмотрите использование AcEditorReactor повторных вызовов случая как альтернатива к ответу на эти сообщения. Не ответьте на эти сообщения, если вы отвечаете на эквивалентные повторные вызовы случая, сделанные через AcEditorReactor.

    Параметры настройки Проекта Visual C++ для Динамически Связанного MFC

    Формировать Приложение ObjectArx, используя общедоступную MFC
    библиотеку
    1 Выбирают MFC AppWizard опция (DLL) для проекта.
    2 Расширение Выбора DLL использование общедоступного MFC DLL.
    3 Идут к диалоговому окну Project Settings и выбирают позицию табуляции General.
    4 Использование Выбора MFC в Общедоступном DLL для поля Microsoft foundation class.
    5 Добавляют функцию acrxEntryPoint к CPP файлу проекта. См. пример в конце главы для законченной установки для проекта MFC.

    Перегрузка deepClone () Функция

    Типовой код в этой секции - приближение  к заданному по умолчанию поведению deepClone(). Глубокая клонируемая операция имеет две основных стадии:
    § Клонирование (Вы можете перегружать эту стадию)
    § Трансляция (Вы не будете должны повторно осуществить эту стадию; это может управляться тем, что помещено в карту ID)
    В течение клонируемой стадии в этом примере, информация относительно старого объекта скопирована к новому объекту, используя определенный тип регистратора, чтобы выписать объект и читать это назад. Регистратор следит за объектами, принадлежащими первичному объекту так, чтобы они могли быть скопированы также.
    Закончить клонируемую стадию
    1 Создают новый объект того же самого типа как старый.
    2 Добавляют новый объект его владельцу.
    § если объект - примитив, его владелец - запись таблицы блоков, и Вы можете использовать appendAcDbEntity().
    § если объект - AcDbObject, его владелец - AcDbDictionary, и Вы можете использовать setAt (), чтобы добавить это к словарю.
    Если бы это - не первичный объект, Вы обычно добавили бы это к базе данных, используя addAcDbObject () и затем идентифицировать ее владельца, использующего setOwnerId ().
    Чтобы устанавливать монопольное использование, владелец должен регистрировать из ID находящегося в собственности объекта, используя соответствующий тип монопольного использования.
    3 Запрос dwgOut () на первоначальном объекте, используя глубокого клонируемого регистратора (AcDbDeepCloneFiler), чтобы выписать объект. (Или, если Вы перегружаете wblockClone () функция, использует AcDbWblockCloneFiler.)
    4 Перематывают регистратора и затем вызывают dwgIn () на новом объекте.
    5 Запроса setObjectIdsInFlux () на каждом новом объекте прежде, чем Вы добавляете его значение к карте объекта ID. Этот важный шаг используется, чтобы указать, что недавно созданный объект - часть глубокой клонируемой операции, и ее объект ID подчинен, чтобы измениться как часть стадии трансляции. Этот флажок автоматически выключен, когда трансляция полна.

    6 Добавляют новую информацию к idMap. IdMap содержит AcDbIdPairs, которые являются парами старого (оригинала) и новых (клонированных) объектных ID. Конструктор для пары ID устанавливает первоначальный объект ID и флажок isPrimary. В этой точке, Вы устанавливаете объект ID для клонированного объекта, устанавливает флажок isCloned в TRUE, и добавляете (назначают) это на idMap.

    7 Клонируют находящиеся в собственности объекты. (Этот шаг рекурсивен.)

    § Спрашивают регистратора, если имеются больше находящиеся в собственности объекты. (Для клона wblock, спросите, если имеются больше жесткие объекты.)

    § чтобы клонировать подобъект, получите его ID, и откройте объект для чтения.

    § Вызывают deepClone () на объекте. (Обратите внимание, что isPrimary установлен в FALSE, потому что это - находящийся в собственности объект.) deepClone () функция клонирует объект и устанавливает его владельца. Это также добавляет запись на карту ID.

    § Закрыли бы подобъект, если это было создано в это время.

    §

    Следующий типовой код иллюстрирует эти шаги:

    Acad::ErrorStatus

    AsdkPoly::deepClone(

    AcDbObject* pOwner,

    AcDbObject*& pClonedObject,

    AcDbIdMapping& idMap,

    Adesk::Boolean isPrimary) const

    {

    // You should always pass back pClonedObject == NULL

    // if, for any reason, you do not actually clone it

    // during this call. The caller should pass it in

    // as NULL, but to be safe, we set it here as well.

    //

    pClonedObject = NULL;

    // If this object is in the idMap and is already

    // cloned, then return.

    //

    bool isPrim = false;

    if (isPrimary)

    isPrim = true;

    AcDbIdPair idPair(objectId(), (AcDbObjectId)NULL, false, isPrim);

    if (idMap.compute(idPair) && (idPair.value() != NULL))

    return Acad::eOk;


    // Step 1: Create the clone.

    //

    AsdkPoly *pClone = (AsdkPoly*)isA()->create();

    if (pClone != NULL)

    pClonedObject = pClone; // Set the return value.

    else

    return Acad::eOutOfMemory;

    // Step 2: Append the clone to its new owner. In this

    // example, the original object is derived from AcDbEntity,

    // so the owner is expected to be an AcDbBlockTableRecord,

    // unless an ownership relationship is set up with another

    // object. In that case, it is important to establish a

    // connection to that owner. This sample shows a generic

    // method using setOwnerId().

    //

    AcDbBlockTableRecord *pBTR =

    AcDbBlockTableRecord::cast(pOwner);

    if (pBTR != NULL) {

    pBTR->appendAcDbEntity(pClone);

    } else {

    if (isPrimary)

    return Acad::eInvalidOwnerObject;

    // Some form of this code is only necessary if

    // anyone has set up an ownership for the object

    // other than with an AcDbBlockTableRecord.

    //

    pOwner->database()->addAcDbObject(pClone);

    pClone->setOwnerId(pOwner->objectId());

    }

    // Step 3: Now contents are copied to the clone. This is done

    // using an AcDbDeepCloneFiler. This filer keeps a list of all

    // AcDbHardOwnershipIds and AcDbSoftOwnershipIds contained in

    // the object and its derived classes. This list is then used

    // to know what additional, "owned" objects need to be cloned

    // below.

    //

    AcDbDeepCloneFiler filer;

    dwgOut(&filer);

    // Step 4: Rewind the filer and read the data into the clone.

    //

    filer.seek(0L, AcDb::kSeekFromStart);

    pClone->dwgIn(&filer);

    // Step 5: This must be called for all newly created objects

    // in deepClone(). It is turned off by endDeepClone()

    // after it has translated the references to their

    // new values.

    //

    pClone->setAcDbObjectIdsInFlux();

    // Step 6: Add the new information to the ID map. We can use

    // the ID pair started above.

    //

    idPair.setValue(pClonedObject->objectId());

    idPair.setIsCloned(Adesk::kTrue);

    idMap.assign(idPair);

    // Step 7: Using the filer list created above, find and clone


    // any owned objects.

    //

    AcDbObjectId id;

    while (filer.getNextOwnedObject(id)) {

    AcDbObject *pSubObject;

    AcDbObject *pClonedSubObject;

    // Some object’ s references may be set to NULL,

    // so don’t try to clone them.

    //

    if (id == NULL)

    continue;

    // Open the object and clone it. Note that "isPrimary" is

    // set to kFalse here because the object is being cloned,

    // not as part of the primary set, but because it is owned

    // by something in the primary set.

    //

    acdbOpenAcDbObject(pSubObject, id, AcDb::kForRead);

    pClonedSubObject = NULL;

    pSubObject->deepClone(pClonedObject,

    pClonedSubObject,

    idMap, Adesk::kFalse);

    // If this is a kDcInsert context, the objects

    // may be "cheap" cloned. In this case, they are

    // "moved" instead of cloned. The result is that

    // pSubObject and pClonedSubObject will point to

    // the same object. Therefore, we only want to close

    // pSubObject if it really is a different object

    // than its clone.

    //

    if (pSubObject != pClonedSubObject)

    pSubObject->close();

    // The pSubObject may either already have been

    // cloned, or for some reason has chosen not to be

    // cloned. In that case, the returned pointer will

    // be NULL. Otherwise, since we have no immediate

    // use for it now, we can close the clone.

    //

    if (pClonedSubObject != NULL)

    pClonedSubObject->close();

    }

    // Leave pClonedObject open for the caller.

    //

    return Acad::eOk;

    }

    Перегрузка saveAs ()

    Вы должны перегрузить saveAs () если Вы хотите сохранить дополнительное графическое представление для сохранения полномочной графики объекта, Выпустите 12 DWG файлы, или оба.
    Если ваш заказной объект не перегружает AcDbEntity:: saveAs () функция, AutoCAD усилит ваш worldDraw () функция, чтобы поддержать полномочную графику объекта или Выпускать 12 DWG файлы. AcDbEntity:: saveAs() просто вызывает worldDraw ().
    virtual void
    AcDbEntity:: saveAs (
    AcGiWorldDraw *pWd,
    AcDb:: SaveType saveType);
    SaveType параметр используется, когда Вы хотите формировать уникальный, чередовать графические представления для обоих видов сохранения; это указывает, для которого цель saveAs () называлась. SaveType параметр имеет любое из следующих значений:
    § kR13Save указывает, что saveAs () назывался, чтобы сохранить{*экономить*} полномочные графические данные.
    § kR12Save указывает, что saveAs () назывался для сохранения, чтобы Выпустить 12 DWG файлы.
    Изнутри saveAs (), Вы можете хотеть назвать worldDraw () функцией для одного значения saveType и делать прямой AcGiWorldGeometry, и AcGiSubEntityTraits запрашивает другого значения, или Вы не можете хотеть назвать worldDraw () функцией вообще.
    В любом случае, перед запросом saveAs (), AutoCAD первые замены геометрия AcGiWorldDraw и черты возражает со специальными подклассами AcGiWorldGeometry и AcGiSubEntityTraits. Геометрический примитив Этих подклассов и функции черт свойства кэшируют данные в соответствующем формате скорее чем выполнение дисплея. После запроса saveAs (), AutoCAD записывает кэшируемые данные на диск.
    Никакой вид сохранения не разрешает сохранять любую графику иждивенца представления. ViewportDraw () функция не называется как часть любой из сохраняющихся операций.
    Ваш заказной объект может полагаться на его viewportDraw () функция для его графики, так ее worldDraw () функция один не произвела бы соответствующее изображение.
    В том случае, вы будете должны перегрузить saveAs () чтобы произвести разумную графику для Выпуска 12 и полномочных объектов.
    Для получения дополнительной информации на полномочных графических данных, см. главу 14, “ Полномочные Объекты. ”
    В Выпуске 12 DWG файлы, информация относительно первоначального объекта не сохранена в файле. Однако, первый Выпуск, 12 объекта будет иметь тот же самый маркер{*дескриптор*} как первоначальный объект, и любой дополнительный Выпуск 12 объектами, будет иметь первоначальный маркер{*дескриптор*} объекта, помещенный в их data. (Просмотр под прикладным названием{*именем*} ACAD, после строкового компонента данных R13OBJECT.) Эта особенность обеспечивается так, чтобы Вы могли группировать Выпуск 12 объектов в блок.

    Перегрузка wblockClone () Функция

    Когда операция клона wblock выполнена, AutoCAD создает имеющую силу базу данных для нового рисунка, который содержит словарь имен объектов, все таблицы идентификаторов, и полный набор переменных заголовка. Следующий код приближает заданное по умолчанию выполнение wblockClone (). Перечисленные шаги соответствуют, те перечисляли в секции “ Перегрузка deepClone () Функцию ” на странице 484.
    WblockClone () функция использует регистратора класса AcDbWblockCloneFiler, который возвращает список жесткого указателя и жестких связей владельца первичного объекта. Прежде, чем Вы вызываете wblockClone () на этих подобъектах, Вы должны проверить владельца подобъекта. В этой точке, вы будете делать одну из двух вещей:
    N, если Вы - владелец объекта, заставляет владельца подобъекта быть клоном вас непосредственно.
    N, если Вы - не владелец объекта, проход в базе данных клона как pOwner параметр в wBlockClone () функциональный запрос. В это время, объект добавлен в конец к новой базе данных, получает объект ID, и помещен в карту ID. Вход карты ID для этого объекта определит FALSE для isOwnerTranslated поля.
    Если pOwner установлен в базу данных, wblockClone () должен установить владельца клонированного объекта тому же самому владельцу как таковой первоначального объекта. Тогда, когда ссылки оттранслированы в соответствии с AutoCAD, это модифицирует ссылку владельца к клонированному объекту в новой базе данных.
    Важно гарантировать, что все объекты обладания клонировались. AutoCAD всегда клонирует таблицы идентификаторов, словарь имен объектов, пространство модели, и пространство листа (для клонируемых контекстов других чем AcDb:: kDcXrefBind) в течение клона wblock. Приложения с обладанием объектов ответствены за обеспечение, чтобы эти объекты клонировались{*имитировались*} в случае необходимости. Если объект обладания не клонировался и не найден в карте ID, wblock клонируемыми аварийными прекращениями работы с AcDb:: eOwnerNotSet.
    Вы должны пройти в базе данных как владелец объекта, когда Вы копируете примитив, которых ссылок таблица идентификаторов делает запись. Например, предположите, что Вы вызываете wblockClone () на объекте сферы. Запись таблицы блоков - жесткий владелец этого объекта сферы. Объект сферы содержит жесткую ссылку к таблице уровня.

    Сначала, в beginDeepClone () стадия, новая база данных создана и основывать с заданными по умолчанию элементами. Следующий рисунок показывает запись таблицы блоков пространства модели и таблицу уровня, потому что они уместны этому разделу. Клонирование, которое происходит в этой стадии всегда, случается в течение wblock операции.

    В beginWblock () стадия, набор выборов клонировался, как показано в следующем рисунке. В этом примере, сфера клонировался.

    Перегрузка wblockClone () Функция

    Поскольку сфера содержит жесткий указатель на Уровень 1, Уровень 1 клонирован.

    Перегрузка wblockClone () Функция

    Перегрузка wblockClone () Функция

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

    Перегрузка wblockClone () Функция

    Карта ID предыдущего рисунка



    KEY



    VALUE



    isCloned



    isPrimary



    isOwnerXlated



    BTR1



    BTR2



    TRUE



    FALSE



    TRUE



    SPH1



    SPH2



    TRUE



    TRUE



    TRUE



    LT1



    LT2



    TRUE



    FALSE



    *



    LTR1



    LTR2



    TRUE



    FALSE



    FALSE†

    * Владелец таблицы уровня - база данных непосредственно, так что этот вход бессмысленен.

    † В течение трансляции, эта установка указывает, что уровень транслирует его владельца от LayerTable 1 к LayerTable 2.

    Процесс клона wblock используется для таблицы перекрестных ссылок, связывают также как wblock. Потребности оба очень похожи, но там - несколько различий, которые требуют специального внимания при перегрузке wblockClone ().

    Wblock клонирует все отобранные примитивы. Однако, таблица перекрестных ссылок связывает, никогда не клонирует примитивы, которые находятся в пространстве листа. Это оставляет две вещи рассмотреть при создании объектов или примитивов, и использования AcDbHardPointerIds. Сначала, в начале wblockClone любого AcDbEntity (), выясните, если клонируемый контекст - AcDb:: kDcXrefBind и, если так, клонируется ли примитив в пространстве листа. Если это, то никакое клонирование не должно быть сделано, и wblockClone () должен возвратить Acad:: eOk.

    Если ваш класс пользователя имеет любой AcDbHardPointerIds, который может указывать на примитивы (типа, мы делаем с AcDbGroup), то примитивы могли бы быть в пространстве листа и не будут поэтому клонироваться. В таком случае, AcDbHardPointerIds будет установлен в NULL.


    Wblock не следует за жесткими ссылками указателя поперек баз данных. Однако, таблица перекрестных ссылок связывает, делает это все время. Например, примитив в рисунке таблицы перекрестных ссылок может быть на VISRETAIN уровне в ведущем рисунке. Так, если Вы осуществляете, ваш wblockClone () с циклом, чтобы проверить подобъекты, и базу данных подобъекта - не тот же самый как таковой клонируемого объекта, Вы должны пропустить подобъект, если клонируемый контекст - не AcDb:: kDcXrefBind. Например:

    if(pSubObject->database() != database() && idMap.deepCloneContext() != AcDb::kDcXrefBind)

    {

    pSubObject->close();

    continue;

    }

    Следующие показы кода, перегружающие wblockClone () чтобы осуществить это для заказного примитива (AsdkPoly). Эта функция вызвана с кодом, показанным в “ Редактор Функции Уведомления Реактора ” на странице 504.

    Acad::ErrorStatus

    AsdkPoly::wblockClone(AcRxObject* pOwner,

    AcDbObject*& pClonedObject,

    AcDbIdMapping& idMap,

    Adesk::Boolean isPrimary) const

    {

    // You should always pass back pClonedObject == NULL

    // if, for any reason, you do not actually clone it

    // during this call. The caller should pass it in

    // as NULL, but to be safe, it is set here as well.

    //

    pClonedObject = NULL;

    // If this is a fast wblock operation, no cloning

    // should take place, so we simply call the base class’s

    // wblockClone() and return whatever it returns.

    //

    // For fast wblock, the source and destination databases

    // are the same, so we can use that as the test to see

    // if a fast wblock is in progress.

    //

    AcDbDatabase *pDest, *pOrig;

    idMap.destDb(pDest);

    idMap.origDb(pOrig);

    if (pDest == pOrig)

    return AcDbCurve::wblockClone(pOwner, pClonedObject, idMap, isPrimary);

    // If this is an xref bind operation and this AsdkPoly

    // entity is in paper space, then we don’t want to

    // clone because xref bind doesn’t support cloning

    // entities in paper space. Simply return Acad::eOk.

    //

    static AcDbObjectId pspace = AcDbObjectId::kNull;


    if (pspace == AcDbObjectId::kNull) {

    AcDbBlockTable *pTable;

    database()->getSymbolTable(pTable, AcDb::kForRead);

    pTable->getAt(ACDB_PAPER_SPACE, pspace);

    pTable->close();

    }

    if ( idMap.deepCloneContext() == AcDb::kDcXrefBind && ownerId() == pspace)

    return Acad::eOk;

    // If this object is in the idMap and is already

    // cloned, then return.

    //

    bool isPrim = false;

    if (isPrimary)

    isPrim = true;

    AcDbIdPair idPair(objectId(), (AcDbObjectId)NULL, false, isPrim);

    if (idMap.compute(idPair) && (idPair.value() != NULL))

    return Acad::eOk;

    // The owner object can be either an AcDbObject or an

    // AcDbDatabase. AcDbDatabase is used if the caller is

    // not the owner of the object being cloned (because it

    // is being cloned as part of an AcDbHardPointerId

    // reference). In this case, the correct ownership

    // will be set during reference translation. If

    // the owner is an AcDbDatabase, then pOwn will be left

    // NULL here, and is used as a "flag" later.

    //

    AcDbObject *pOwn = AcDbObject::cast(pOwner);

    AcDbDatabase *pDb = AcDbDatabase::cast(pOwner);

    if (pDb == NULL)

    pDb = pOwn->database();

    // Step 1: Create the clone.

    //

    AsdkPoly *pClone = (AsdkPoly*)isA()->create();

    if (pClone != NULL)

    pClonedObject = pClone; // Set the return value.

    else

    return Acad::eOutOfMemory;

    // Step 2: If the owner is an AcDbBlockTableRecord, go ahead

    // and append the clone. If not, but we know who the

    // owner is, set the clone’s ownerId to it. Otherwise,

    // we set the clone’s ownerId to our own ownerId (in

    // other words, the original ownerId). This ID will

    // then be used later, in reference translation, as

    // a key to finding who the new owner should be. This

    // means that the original owner must also be cloned at

    // some point during the wblock operation.

    // EndDeepClone’s reference translation aborts if the

    // owner is not found in the ID map.

    //

    // The most common situation where this happens is

    // AcDbEntity references to symbol table records, such


    // as the layer an entity is on. This is when you will

    // have to pass in the destination database as the owner

    // of the layer table record. Since all symbol tables

    // are always cloned in wblock, you do not need to make

    // sure that symbol table record owners are cloned.

    //

    // However, if the owner is one of your own classes,

    // then it is up to you to make sure that it gets

    // cloned. This is probably easiest to do at the end

    // of this function. Otherwise you may have problems

    // with recursion when the owner, in turn, attempts

    // to clone this object as one of its subobjects.

    //

    AcDbBlockTableRecord *pBTR = NULL;

    if (pOwn != NULL)

    pBTR = AcDbBlockTableRecord::cast(pOwn);

    if (pBTR != NULL) {

    pBTR->appendAcDbEntity(pClone);

    } else {

    pDb->addAcDbObject(pClonedObject);

    pClone->setOwnerId( (pOwn != NULL) ? pOwn->objectId() : ownerId());

    }

    // Step 3: The AcDbWblockCloneFiler makes a list of

    // AcDbHardOwnershipIds and AcDbHardPointerIds. These

    // are the references that must be cloned during a

    // wblock operation.

    //

    AcDbWblockCloneFiler filer;

    dwgOut(&filer);

    // Step 4: Rewind the filer and read the data into the clone.

    //

    filer.seek(0L, AcDb::kSeekFromStart);

    pClone->dwgIn(&filer);

    // Step 5:

    // This must be called for all newly created objects

    // in wblockClone. It is turned off by endDeepClone()

    // after it has translated the references to their

    // new values.

    //

    pClone->setAcDbObjectIdsInFlux();

    // Step 6: Add the new information to the ID map. We can use

    // the ID pair started above. We must also let the

    // idMap entry know whether the clone’s owner is

    // correct, or needs to be translated later.

    //

    idPair.setIsOwnerXlated((Adesk::Boolean)(pOwn != NULL));

    idPair.setValue(pClonedObject->objectId());

    idPair.setIsCloned(Adesk::kTrue);

    idMap.assign(idPair);

    // Step 7: Using the filer list created above, find and clone

    // any hard references.

    //

    AcDbObjectId id;

    while (filer.getNextHardObject(id)) {


    AcDbObject *pSubObject;

    AcDbObject *pClonedSubObject;

    // Some object references may be set to NULL,

    // so don’t try to clone them.

    //

    if (id == NULL)

    continue;

    // If the referenced object is from a different

    // database, such as an xref, do not clone it.

    //

    acdbOpenAcDbObject(pSubObject, id, AcDb::kForRead);

    if (pSubObject->database() != database()) {

    pSubObject->close();

    continue;

    }

    // To find out if this is an AcDbHardPointerId

    // versus an AcDbHardOwnershipId, check if we are the

    // owner of the pSubObject. If we are not,

    // then we cannot pass our clone in as the owner

    // for the pSubObject’s clone. In that case, we

    // pass in our clone’s database (the destination

    // database).

    //

    // Note that "isPrimary" is set to kFalse here

    // because the object is being cloned, not as part

    // of the primary set, but because it is owned by

    // something in the primary set.

    //

    pClonedSubObject = NULL;

    if (pSubObject->ownerId() == objectId()) {

    pSubObject->wblockClone(pClone,

    pClonedSubObject,

    idMap, Adesk::kFalse);

    } else {

    pSubObject->wblockClone(

    pClone->database(),

    pClonedSubObject,

    idMap, Adesk::kFalse);

    }

    pSubObject->close();

    // The pSubObject may either already have been

    // cloned, or for some reason has chosen not to be

    // cloned. In that case, the returned pointer will

    // be NULL. Otherwise, since there is no immediate

    // use for it now, the clone can be closed.

    //

    if (pClonedSubObject != NULL)

    pClonedSubObject->close();

    }

    // Leave pClonedObject open for the caller.

    //

    return Acad::eOk;

    }

    ПРИМЕЧАНИЕ Помните, что, когда wblock () функция находится в процессе выполнения, ссылки указателя в базе данных адресата еще не были оттранслированы. Следующий код не работает правильно, потому что, хотя это пробует открывать запись таблицы блоков пространства модели базы данных адресата, запись таблицы блоков пространства модели исходной базы данных открыта вместо этого. Неоттранслированная ссылка в таблице блоков базы данных адресата - все еще что касается пространства модели исходной базы данных.


    void

    AsdkWblockReactor::otherWblock(

    AcDbDatabase* pDestDb,

    AcDbIdMapping& idMap,

    AcDbDatabase* pSrcDb)

    {

    AcDbBlockTable *pDestBlockTable;

    AcDbBlockTableRecord *pDestBTR;

    pDestDb->getSymbolTable(pDestBlockTable, AcDb::kForRead);

    pDestBlockTable->getAt(ACDB_MODEL_SPACE, pDestBTR, AcDb::kForRead);

    pDestBlockTable->close();

    // Now pDestBTR is pointing to pSrcDb database’s model

    // space, not to the destination database’s model space!

    // The code above is not correct!

    }

    Чтобы находить пространство модели адресата, Вы должны смотреть это в карте ID:

    void

    AsdkWblockReactor::otherWblock(

    AcDbDatabase* pDestDb,

    AcDbIdMapping& idMap,

    AcDbDatabase* pSrcDb)

    {

    // To find the destination model space, you must look

    // it up in the ID map:

    AcDbBlockTable *pSrcBlockTable;

    pSrcDb->getSymbolTable(pSrcBlockTable, AcDb::kForRead);

    AcDbObjectId srcModelSpaceId;

    pSrcBlockTable->getAt(ACDB_MODEL_SPACE, srcModelSpaceId);

    pSrcBlockTable->close();

    AcDbIdPair idPair;

    idPair.setKey(srcModelSpaceId);

    idMap.compute(idPair);

    AcDbBlockTableRecord *pDestBTR;

    acdbOpenAcDbObject((AcDbObject*&)pDestBTR,

    idPair.value(), AcDb::kForRead, Adesk::kTrue);

    }

    Перегрузка worldDraw () и viewportDraw ()

    AutoCAD называет worldDraw () и viewportDraw () функциями, чтобы отобразить объект. Вы должны осуществить worldDraw () функция для любого класса, полученного из AcDbEntity. ViewportDraw () функция необязательный.
    virtual Adesk::Boolean
    AcDbEntity::worldDraw( AcGiWorldDraw *pWd);
    virtual void
    AcDbEntity::viewportDraw( AcGiViewportDraw *pVd);
    Всякий раз, когда AutoCAD должен восстановить графику, чтобы отобразить объект, worldDraw () и viewportDraw () функции называются следующим способом:
    if (!entity->worldDraw(pWd))
    for (each relevant viewport)
    entity->viewportDraw(pVd);
    WorldDraw() функция формирует часть из графического представления объекта, которое может быть определено независимо от любой частности modelspace представление{*вид*} или бумажно - пространственные контексты области просмотра. ViewportDraw () функция тогда формирует часть иждивенца представления из графики объекта. Если любая из графики объекта - иждивенец представления, worldDraw() функция должна возвратить kFalse и viewportDraw () функция должна быть осуществлена. Наоборот, если объект не имеет никакой графики иждивенца представления, то worldDraw() должна возвратить kTrue, и заказной объект не осуществляет ViewportDraw().
    AcDbEntity:: worldDraw () функция берет указатель на объект AcGiWorldDraw. AcGiWorldDraw - контейнерный класс для AcGi геометрии и объектов черт. Определенно, AcGiWorldDraw содержит два других объекта:
    § AcGiWorldGeometry
    § AcGiSubEntityTraits
    К  объекту AcGiWorldGeometry можно обращаться изнутри worldDraw(),  используя AcGiWorldDraw::geometry(), и объект AcGiSubEntityTraits можно обращаться,  используя
    AcGiWorldDraw:: subEntityTraits() функция. Векторы записей объекта AcGiWorldGeometry к AutoCAD освежают память, используя ее набор рисунка примитивов. Примитив - команда с  самым низким уровнем Используемым, чтобы тянуть{*рисовать*} графические объекты. Объект для геометрии имеет следующие функции для рисунка примитивов во внешних мировых координатах:

    § Circle

    § Circular arc

    § Polyline

    § Polygon

    § Mesh

    § Shell

    § Text

    § Xline

    § Ray

    Объект AcGiSubEntityTraits устанавливает графические атрибуты со значением, использующие его набор функций черт:

    § Color

    § Layer

    § Linetype

    § Polygon fill type

    § Selection marker

     AcDbEntity:: viewportDraw () функция берет указатель на объект AcGiViewportDraw и формирует представление-определенное представление объекта. Область просмотра тянет{*рисует*} объект - также контейнерный объект для других объектов, которые включают следующее:

    § AcGiViewportGeometry

    § AcGiSubEntityTraits

    § AcGiViewport

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

    § polylineEye ()

    § polygonEye ()

    § polylineDc ()

    § polygonDc ()

    Объект черт подобъекта области просмотра - тот же самый, поскольку используемое миром рисует объект (AcGiSubEntityTraits). Объект области просмотра обеспечивает функции для запроса матриц преобразования области просмотра и рассмотрения параметров.

    ПРЕДУПРЕЖДЕНИЕ! Объект AcGi типа AcGiWorldDraw или AcGiViewportDraw не должен быть сохранен как глобальная или статическая переменная. Не сохраните копии объектов AcGi поперек запросов к worldDraw () и viewportDraw () функции. Однажды это возвращение функций, объекты AcGi больше не допустимы.

    Для получения дополнительной информации относительно AcGi библиотеки, см. главу 26, “ Графическая Библиотека Интерфейсов. ”

    Переменные, типы и значения, определенные в ObjectARX

    ObjectARX
    определяет несколько типов данных для среды AutoCAD. Это также определяет множество символических кодов для значений, которые пропускают функции (или просто для общей ясности). Наконец, это объявляет и инициализирует несколько глобальных переменных.
    Определения и объявления появляются в ObjectARX
    файлах заголовка.
    ОБРАТИТЕ ВНИМАНИЕ, не ли приложение твердо придерживается соглашений, наложенных по определениям и объявлениям, описанным в этой главе, будет трудно читать и поддержать в лучшем; в худшем случае, это не будет связываться с AutoCAD правильно. Также, будущие версии ObjectARX могут вовлекать изменения к файлам заголовка. Поэтому, не замените целочисленную константу на ее символический код, если такой код был определен.

    Пересечение с Другими примитивами

    IntersectWith () функция имеет две формы:
    virtual Acad::ErrorStatus
    intersectWith(
    const AcDbEntity* ent,
    AcDb::Intersect intType,
    AcGePoint3dArray& points,
    int thisGsMarker = 0,
    int otherGsMarker = 0) const;
    virtual Acad::ErrorStatus
    intersectWith(
    const AcDbEntity* ent,
    AcDb::Intersect intType,
    const AcGePlane& projPlane,
    AcGePoint3dArray& points,
    int thisGsMarker = 0,
    int otherGsMarker = 0) const;
    Первая форма intersectWith () функциональные испытания на простое пересечение двух объектов. Вторая форма вычисляет пересечение на проекционную плоскость. Однако, обе функции возвращают перекрестные пункты{*точки*} на объекте непосредственно.
    Использовать проекционную плоскую форму intersectWith () функция
    1 Проектируют ваш объект и объект параметра на плоскость.
    2 Проверяют объекты на пересечение на проекционной плоскости.
    3 Проектируют перекрестные пункты{*точки*} назад на объект и возвращают их.
    Заказной AsdkPoly класс перегружает обеих формы intersectWith () функция.
    Acad::ErrorStatus
    AsdkPoly::intersectWith(
    const AcDbEntity* ent,
    AcDb::Intersect intType,
    AcGePoint3dArray& points,
    int /*thisGsMarker*/,
    int /*otherGsMarker*/) const
    {
    assertReadEnabled();
    Acad::ErrorStatus es = Acad::eOk;
    if (ent == NULL)
    return Acad::eNullEntityPointer;
    // The idea is to intersect each side of the polygon
    // with the given entity and return all the points.
    //
    // For non-R12-entities with intersection methods defined,
    // we call that method for each of the sides of the polygon.
    // For R12-entities, we use the locally defined intersectors,
    // since their protocols are not implemented.
    //
    if (ent->isKindOf(AcDbLine::desc())) {
    if ((es = intLine(this, AcDbLine::cast(ent),
    intType, NULL, points)) != Acad::eOk)
    {
    return es;
    }
    } else if (ent->isKindOf(AcDbArc::desc())) {
    if ((es = intArc(this, AcDbArc::cast(ent), intType,
    NULL, points)) != Acad::eOk)
    {
    return es;
    }
    } else if (ent->isKindOf(AcDbCircle::desc())) {

    if ((es = intCircle(this, AcDbCircle::cast(ent),

    intType, NULL, points)) != Acad::eOk)

    {

    return es;

    }

    } else if (ent->isKindOf(AcDb2dPolyline::desc())) {

    if ((es = intPline(this, AcDb2dPolyline::cast(ent),

    intType, NULL, points)) != Acad::eOk)

    {

    return es;

    }

    } else if (ent->isKindOf(AcDb3dPolyline::desc())) {

    if ((es = intPline(this, AcDb3dPolyline::cast(ent),

    intType, NULL, points)) != Acad::eOk)

    {

    return es;

    }

    } else {

    AcGePoint3dArray vertexArray;

    if ((es = getVertices3d(vertexArray))

    != Acad::eOk)

    {

    return es;

    }

    if (intType == AcDb::kExtendArg

    || intType == AcDb::kExtendBoth)

    {

    intType = AcDb::kExtendThis;

    }

    AcDbLine *pAcadLine;

    for (int i = 0; i < vertexArray.length() - 1; i++) {

    pAcadLine = new AcDbLine();

    pAcadLine->setStartPoint(vertexArray[i]);

    pAcadLine->setEndPoint(vertexArray[i + 1]);

    pAcadLine->setNormal(normal());

    if ((es = ent->intersectWith(pAcadLine, intType,

    points)) != Acad::eOk)

    {                             

    delete pAcadLine;

    return es;

    }

    delete pAcadLine;

    }

    }

    return es;

    }

    Acad::ErrorStatus

    AsdkPoly::intersectWith(

    const AcDbEntity* ent,

    AcDb::Intersect intType,

    const AcGePlane& projPlane,

    AcGePoint3dArray& points,

    int /*thisGsMarker*/,

    int /*otherGsMarker*/) const

    {

    assertReadEnabled();

    Acad::ErrorStatus es = Acad::eOk;

    if (ent == NULL)

    return Acad::eNullEntityPointer;

    // The idea is to intersect each side of the polygon

    // with the given entity and return all the points.

    //

    // For non-R12-entities, with intersection methods defined,

    // we call that method for each of the sides of the polygon.

    // For R12-entities, we use the locally defined intersectors,

    // since their protocols are not implemented.

    //

    if (ent->isKindOf(AcDbLine::desc())) {

    if ((es = intLine(this, AcDbLine::cast(ent),

    intType, &projPlane, points)) != Acad::eOk)

    {

    return es;

    }

    } else if (ent->isKindOf(AcDbArc::desc())) {

    if ((es = intArc(this, AcDbArc::cast(ent), intType,


    &projPlane, points)) != Acad::eOk)

    {

    return es;

    }

    } else if (ent->isKindOf(AcDbCircle::desc())) {

    if ((es = intCircle(this, AcDbCircle::cast(ent),

    intType, &projPlane, points)) != Acad::eOk)

    {

    return es;

    }

    } else if (ent->isKindOf(AcDb2dPolyline::desc())) {

    if ((es = intPline(this, AcDb2dPolyline::cast(ent),

    intType, &projPlane, points)) != Acad::eOk)

    {

    return es;

    }

    } else if (ent->isKindOf(AcDb3dPolyline::desc())) {

    if ((es = intPline(this, AcDb3dPolyline::cast(ent),

    intType, &projPlane, points)) != Acad::eOk)

    {

    return es;

    }

    } else {

    AcGePoint3dArray vertexArray;

    if ((es = getVertices3d(vertexArray))

    != Acad::eOk)

    {

    return es;

    }

    if (intType == AcDb::kExtendArg

    || intType == AcDb::kExtendBoth)

    {

    intType = AcDb::kExtendThis;

    }

    AcDbLine *pAcadLine;

    for (int i = 0; i < vertexArray.length() - 1; i++) {

    pAcadLine = new AcDbLine();

    pAcadLine->setStartPoint(vertexArray[i]);

    pAcadLine->setEndPoint(vertexArray[i + 1]);

    pAcadLine->setNormal(normal());

    if ((es = ent->intersectWith(pAcadLine, intType,

    projPlane, points)) != Acad::eOk)

    {

    delete pAcadLine;

    return es;

    }

    delete pAcadLine;

    }

    // All the points that we selected in this process are on

    // the other curve; we are dealing with apparent

    // intersection. If the other curve is 3D or is not

    // on the same plane as poly, the points are not on

    // poly.

    //

    // In this case, we need to do some more work. Project the

    // points back onto the plane. They should lie on

    // the projected poly. Find points on real poly

    // corresponding to the projected points.

    //

    AcGePoint3d projPt, planePt;

    AcGePoint3dArray pts;

    AcGeLine3d line;

    AcGePlane polyPlane;

    AcDb::Planarity plnrty;

    getPlane(polyPlane,plnrty);

    for (i = 0; i < points.length(); i++) {

    // Define a line starting from the projPt and

    // along the normal. Intersect the polygon with

    // that line. Find all the points and pick the

    // one closest to the given point.

    //

    projPt = points[i].orthoProject(projPlane);

    line.set(projPt, projPlane.normal());

    if ((es = intLine(this, line, pts))

    != Acad::eOk)

    {

    return es;

    }

    planePt = projPt.project(polyPlane,

    projPlane.normal());

    points[i] = pts[0];

    double length = (planePt - pts[0]).length();

    double length2;

    for (int j = 1; j < pts.length(); j++) {

    if ((length2 = (planePt - pts[j]).length())

    < length)

    {

    points[i] = pts[j];

    length = length2;

    }

    }

    }

    }

    return es;

    }

    Пересечение точек

    IntersectWith () функция возвращает пункты{*точки*}, где примитив пересекает другой примитив в рисунке. Входные значения для этой функции - примитив и перекрестный тип, который может быть один из следующего:
    §
    kOnBothOperands (никакой примитив расширен{*продлен*})
    § kExtendThis
    § kExtendArg
    § kExtendBoth
    Например, предположите, что рисунок содержит три строки, показанные в следующей иллюстрации. Line1 - "это" и line3 - примитив параметра. Если перекрестный тип - kExtendThis, пункт{*точка*} возвращен как пункт{*точка*}, где line1 ("это") пересек бы line3, если line1 были расширены{*продлены*}. Если перекрестный тип - kExtendArgument, и line2 - примитив параметра, никакие данные не возвращены, потому что, даже если это было расширено{*продлено*}, line2 не будет пересекать line1. Если перекрестный тип - kExtendBoth, и line2 - примитив параметра, пункт{*точка*} B возвращен. Если перекрестный тип - kExtendNone, и line2 - примитив параметра, никакие данные не возвращены.
    IntersectWith () функция - перезагруженная функция с двумя формами.
    Вторая форма берет дополнительный параметр, который является самолетом проектирования для определения очевидного пересечения двух примитивов. Они - сигнатуры для intersectWith () функция:
    virtual Acad::ErrorStatus
    AcDbEntity::intersectWith(
    const AcDbEntity* ent,
    AcDb::Intersect intType,
    AcGePoint3dArray& points,
    int thisGsMarker = 0,
    int otherGsMarker = 0) const;
    virtual Acad::ErrorStatus
    AcDbEntity::intersectWith(
    const AcDbEntity* ent,
    AcDb::Intersect intType,
    const AcGePlane& projPlane,
    AcGePoint3dArray& points,
    int thisGsMarker = 0,
    int otherGsMarker = 0) const;
    Возвращенные пункты{*точки*} - всегда на примитиве ("this"). Поэтому, в случаях{*делах*} очевидного пересечения, пересеченные пункты{*точки*} проектируются назад к примитиву прежде, чем они возвращены.
    Обе версии intersectWith () функция позволяют Вам снабжать необязательные GS маркеры, чтобы оптимизировать выполнение{*работу*} для этой функции. Если intersectWith примитива () функция осуществила использование GS маркеров, то поставляющий{*снабжающий*} GS маркеры может ограничивать перекрестную область и ускорять испытание.
    Например, в следующем рисунке, если пользователь выбирает, одна строка многоугольника, проходящего в GS маркере для той строки устраняет потребность проверить другие пять строк многоугольника.

    Пересечение Заказного Примитива с Другим Примитивом

    ObjectARX - открытая архитектура, где множественные приложения могут осуществлять их собственные заказные объекты. Возможно, что множественные приложения будут загружены в то же самое время в сеансе AutoCAD. Пользователь мог бы выбирать ваш заказной объект в операции, которая заставляет это пересекаться с другим заказным объектом, который Вы не знаете. Следующие рекомендации должны помочь Вам осуществить intersectWith () функция вашего заказного объекта.
    § Каждый заказной объект, как ожидается,  будет способным пересечься с родными объектами. Родные объекты - объекты, определенные в AutoCAD, например, AcDbLine, AcDbEllipse, и AcDbSpline.
    § если intersectWith () функция вашего заказного объекта называется с другим объектом, который - не родной объект, Вы должны взорвать ваш заказной объект (например, используя взрывающийся () функция) к набору распознаваемых родных объектов, затем поворачивать вокруг и вызывать{*называть*} intersectWith () на объекте, который вошел как параметр к вашему intersectWith () в функцию. Поскольку каждый, как ожидается,  будет способным пересечься с родными объектами, объект в параметре был бы способен пересечься с вашей вырезанной версией.
    В течение этого процесса, Вы должны быть внимательным относительно того, как Вы называете intersectWith () функцией параметра и как Вы интерпретируете пункты{*точки*}, которые являются результатами пересечения. Например, если бы перекрестный тип был kExtendArg, Вы хотели бы изменить{*заменить*} это к kExtendThis перед запросом intersectWith () на параметре. Точно так же, если пересечение - очевидное пересечение на плоскости проектирования, пункты{*точки*}, возвращенные от intersectWith () обращаются к объекту параметра, будет на объекте параметра, не обязательно на вашем объекте. Вы, как предполагается,  возвращаете перекрестные пункты{*точки*} на вашем объекте; поэтому, Вы должны проектировать пункты{*точки*} назад на плоскость проектирования (где они будут лежать на вашем проектируемом объекте) и затем проектировать их назад на ваш объект перед возвращением.

    Поддержка Версии объекта

    Несколько механизмов прежде использовались для руководящих версий заказных объектных классов, используемых в Приложениях ObjectArx:
    §
    Переименование класса для каждой новой версии.
    § Поддержание номера версии как первый компонент данных класса.
    § Поддержание номера версии как расширенные данные (xdata) или в словаре расширения.
    Эти механизмы были заменены классом versioning система.
    Эти более ранние механизмы описаны ниже (после описания класса versioning), помогать обслуживать{*поддерживать*} код, который использует их.

    Подготовка к Разгрузке

    Когда ваше приложение разгружено, Вы должны очистить любые заказные классы или
    Команды, которые ваше приложение создало. Это должно иметь место в AcRx:: kUnloadAppMsg случае вашего acrxEntryPoint () функция, или в функции Названный от того случая.
    Разгрузить приложение ObjectARX
    1, если Вы создали команды с acedRegCmds макрокомандой или acedDefun (), Удалите их. Обычно ObjectARX команды удалены группами, использованием AcedRegCmds- > removeGroup ().
    2, если Вы создали заказные классы, удаляют их.
    Используйте deleteAcRxClass () функция, чтобы удалить ваши заказные классы из AcRx дерево во время выполнения. Классы должны быть удалены, начинаясь с Полученные классы сначала, подготавливая дерево классов к родительским классам.
    3 Удаляют любые объекты, добавленные приложением.
    Не имеется никакого способа сообщить AutoCAD забывать относительно AcDbObject образцов это
    Являются в настоящее время резидентом в базе данных. Однако, когда приложение Разгруженный, AutoCAD автоматически повернет такие объекты в образцы AcDbProxyObject или AcDbProxyEntity.
    4 Удаляют любые реакторы, которые были приложены к любому AcDbObject, AcDbDatabase, AcRxDynamicLinker, или объект{*цель*} AcEditor. (Постоянные реакторы На AcDbObjects - исключение; они станут полномочными объектами, когда Приложение разгружено.)
    5, если Вы создали,  сервисное название, удаляет это.
    Вы можете использовать AcrxServiceDictionary- >, удаляют () функцию, чтобы удалить любого
    Обслуживание{*служба*}, которое ваше приложение имеет буферизованный. См. распечатку для
    AcrxServiceDictionary в ObjectARX Ссылке{*справочниках*}.

    Подготовка

    Границы Обрезки закрыты, не-самопересекающиеся, вогнутые 2-ые многоугольники.
    Необязательная передняя сторона и назад Z отсекающие значения может быть назначена. Граница обрезки выражена в произвольной системе координат относительно отсекаемых объектов.
    В AutoCAD, когда пользователь определяет,  граница отсечения для блока, направления вида и завихрения текущего вида используется, чтобы определить координатную систему для границы обрезки. Это могло бы быть тот же самый как система координат отсекаемой блок-ссылки. Это отражено в API в соответствии с условием преобразования к пространству отсечения от системы блок-ссылки:
    Подготовка
    Границы Обрезки могут быть вложены. Составной объект может определять границу отсечения, и объекты, которые это содержит, может также определять границы для их внутренней геометрии. В этом случае, вложенная геометрия сначала отсечена против границы ее родителя, и любые результирующие фрагменты тогда отсечены против границы обрезки внешнего блока.

    Подробности относительно областей просмотра

    Имеются несколько тонкости относительно различной области просмотра, напечатывает AcDb, которые стоят обзор.
    Объект AcDbDatabase может содержать и области просмотра пространства листа и пространство модели.
    Они представлены различными типами AcDb внутренне.
    Области просмотра Пространства модели представлены AcDbViewportTableRecords, которые содержатся в AcDbViewportTable. Они полностью несвязанны с AcDbViewport примитивами. Выпуск AutoCAD 13 и выше требует существования по крайней мере одного AcDbViewportTableRecord в AcDbViewportTable. Это будет названо “*ACTIVE”, который подразумевает, что это была активная область просмотра, когда рисунок был сохранен. Больше чем одна область просмотра могут быть “*ACTIVE” одновременно. Незаконно иметь ViewportTableRecord без имени.
    Области просмотра Пространства листа представлены AcDbViewport. Они могут только существовать в пределах записи таблицы блоков пространства листа AcDbBlockTable. Само пространство листа должно иметь основную область просмотра пространства листа как AcDbViewport примитив в записи таблицы блоков пространства листа. В AutoCAD, эта заданная по умолчанию область просмотра создана автоматически, когда TILEMODE 0 команды выполнен. Имеется предположение в API, что эта область просмотра будет создана автоматически. Таким образом, когда новый AcDbViewport инициализирован и добавлен к записи таблицы блоков пространства листа, если основная область просмотра пространства листа еще не существует, это будет создано в течение завершения нового AcDbViewport. Обратите внимание, что это означает, что никогда не необходимо создать основную область просмотра пространства листа явно. Это совершенно имеет силу, чтобы добавить примитивы к пространству листа без когда-либо создания области просмотра пространства листа. Это - то, потому что AutoCAD может успешно открывать рисунок этого характера и автоматически создаст основную область просмотра пространства листа первый раз, когда TILEMODE, 0 команды используется. AutoCAD должен правильно отобразить примитивы в записи таблицы блоков пространства листа в пределах основной области просмотра пространства листа в то время.
    В ObjectDBX, AcDbViewport::number () функция будет всегда возвращаться -1.
    В ObjectARX, это сообщает о номере области просмотра текущей области просмотра в редакторе AutoCAD. Поскольку AutoCAD – не активен в ObjectDBX, это значение не имеет никакого значения. ObjectDBX обеспечивает acdbGetCurVportId () функцией, которая возвращает текущий объект ID области просмотра, когда рисунок был сохранен.
    Строго рекомендуется, чтобы Вы делали обзор ObjectARX SDK документация относительно областей просмотра всех типов.

    Поиск активных областей просмотра в пространстве модели

    При создании нового DWG файла с AcDbDatabase (Adesk:: kTrue) конструктор, Вы должны установить заданную по умолчанию область просмотра пространства модели в некоторые разумные параметры. Это будет гарантировать, что DWG будет видим в AutoCAD когда открыто. Отказ устанавливать заданную по умолчанию область просмотра пространства модели может требовать, чтобы  пользователь AutoCAD, чтобы выбрать Изменил масштаб изображения Всех, чтобы делать геометрию из видимого рисунка. Кроме того, некоторые примитивы AutoCAD требуют, чтобы разумные параметры области просмотра вычислили аспекты их появления. Например, объект AcDbSpline, созданный в ObjectDBX, и сохраненный к рисунку без любого внимания к области просмотра, может отображать с острыми углами, подобно pline, когда загружено в AutoCAD. Данные не повреждены и первый раз, когда примитив отредактирован в AutoCAD,  AcDbSpline возвратится к его надлежащей форме.
    Однако, это конечно дезориентирует пользователям рисунков вашей программы.
    Разработчики, обладающие утвержденным - позволенным AutoCAD, вероятно,  будут видеть, утверждает результат assert() при загрузке рисунка, который был сохранен без надлежащего внимания к области просмотра. Экспериментирование демонстрирует, который параметры являются лучшими для вашего приложения и геометрии. Чтобы устанавливать область просмотра пространства модели, вставьте следующее:
    // Набор некоторая информация области просмотра.
    AcDbViewportTable* pViewportTable;
    if (db.getViewportTable(pViewportTable, AcDb::kForRead) == Acad::eOk)
    {
    // Find the first viewport and open it for write.
    AcDbViewportTableRecord *pRecord;
    if (pViewportTable->getAt( "*ACTIVE", pRecord, AcDb::kForWrite) == Acad::eOk)
    {
    pRecord->setCenterPoint(AcGePoint2d(0.5, 0.5));
    pRecord->setHeight(1.0);
    pRecord->setWidth(1.0);
    pRecord->close();
    }
    pViewportTable->close();
    }

    Поиск Файла

    AcedFindFile () функция дает возможность приложению искать файл специфического имени. Приложение может определить каталог, чтобы искать, или это может использовать поток путь библиотеки AutoCAD.
    В следующем типовом кодовом фрагменте, acedFindFile () ищет требуемое имя файла согласно пути библиотеки AutoCAD.
    char *refname = "refc.dwg";
    char fullpath[100];
    .
    .
    .
    if (acedFindFile(refname, fullpath) != RTNORM) {
    acutPrintf("Could not find file %s.\n", refname);
    return BAD;
    Если запрос к acedFindFile () успешен, fullpath параметр установлен в полностью квалифицированную строку имени пути, типа следующего:
    /home/work/ref/refc.dwg
    Вы можете также запрашивать пользователей вводить имя файла посредством стандарта файловое диалоговое окно AutoCAD. Чтобы отображать файловое диалоговое окно, вызовите acedGetFileD ().
    Следующий типовой кодовый фрагмент использует файловое диалоговое окно, чтобы запросить пользователей относительно имени ObjectARX-приложения.
    struct resbuf *result;
    int rc, flags;
    if (result = acutNewRb(RTSTR) == NULL) {
    acdbFail("Unable to allocate buffer\n");
    return BAD;
    }
    result->resval.rstring=NULL;
    flags = 2; // Disable the "Type it" button.
    rc = acedGetFileD("Get ObjectARX Application", // Title
    "/home/work/ref/myapp", // Default pathname
    NULL, // The default extension: NULL means "*".
    flags, // The control flags
    result); // The path selected by the user.
    if (rc == RTNORM)
    rc = acedArxLoad(result->resval.rstring);

    Поиск расширенных данных

    Приложение может получить зарегистрированные расширенные данные,  вызывая acdbEntGetX () функция, которая является подобной acdbEntGet (). В то время как acdbEntGet () возвращает только данные определения, acdbEntGetX () возвращает оба
    Данные определения и расширенные данные для приложений это запрашивают. Это требует дополнительного параметра, приложений, который определяет прикладные названия  (это отличается от AutoLISP, в котором (entget) функция была расширена на ввод необязательный параметр, который определяет прикладные названия).
    Названия прошли к acdbEntGetX () должен соответствовать приложениям, зарегистрированным предыдущим запросом к acdbRegApp (); они могут также содержать групповые символы. Если параметр приложений - указатель NULL, запрос к acdbEntGetX () идентичен acdbEntGet () запрос.
    Следующий типовой кодовый фрагмент показывает типичной последовательности для восстановления{*поиска*} расширенных{*продленных*} данных для двух указанных приложений. Обратите внимание, что параметр приложений передает прикладные названия в связанных буферах результатов.
    static struct resbuf appname2 = {NULL, RTSTR},
    appname1 = {&appname2, RTSTR},
    *working_ent;
    strsave(appname1.rstring, "MY_APP_1");
    strsave(appname2.rstring, "SOMETHING_ELSE");
    .
    .
    .
    // Only extended data from "MY_APP_1" and
    // "SOMETHING_ELSE" are retrieved:
    working_ent = acdbEntGetX(&work_ent_addr, &appname1);
    if (working_ent == NULL) {
    // Gracefully handle this failure.
    .
    .
    .
    }
    // Update working entity groups.
    status = acdbEntMod(working_ent);
    // Only extended data from registered applications still in the
    // working_ent list are modified.
    Как типовые показы кода, расширенные данные, отысканные acdbEntGetX() функция может изменяться последующим запросом к acdbEntMod (), также, как acdbEntMod () используется, чтобы изменить нормальные данные определения. (Расширенные данные могут также быть созданы,  определяя, это в списке примитива прошло к acdbEntMake ()).
    При возвращении расширенных данных только определенно требуемые приложения защищают одно приложение от повреждения данных другого приложения. Это также управляет объемом памяти что прикладные использования, и упрощает расширенную обработку данных, которую приложение исполняет.
    ОБРАТИТЕ ВНИМАНИЕ, поскольку строки прошли с приложениями, может включать групповые символы, прикладное имя “*” заставит acdbEntGetX () возвращать все расширенные данные, приложенные примитиву.

    Полезные значения

    ObjectARX
    определяет следующие директивы препроцессора:
     #define TRUE 1
     #define FALSE 0
     #define EOS'\0 ’ // Строковый символ завершения
    Символ ПАУЗЫ, строка, которая содержит единственную наклонную черту влево, определен для acedCommand () и acedCmd () функции, следующим образом:
     #define PAUSE "\\" // Пауза в списке параметров команды
    ОБРАТИТЕ ВНИМАНИЕ, что  ObjectARX библиотека не определяет значения, ХОРОШИЕ и ПЛОХИЕ, которые появляются как возвращаемые значения в выборках кода повсюду этого руководства (особенно по ошибке -обрабатывающий код). Вы можете определять их, если Вы хотите, или заменяете соглашение, которое Вы предпочитаете.

    Полилиния

    Pline () функция позволяет заказному примитиву рисовать графические примитивы, использующие AcDbPolyline как шаблон:
    virtual Adesk::Boolean pline(
    const AcDbPolyline& lwBuf,
    Adesk::UInt32 fromIndex = 0,
    Adesk::UInt32 numSegs = 0) const;
    AcDbPolylines мультисегментированы и поддерживают прямо и изогнутые доли с или без ширины. Использование pline () обеспечивает способность генерировать смежные прямые и изогнутые доли с шириной. Ни один из других AcGi
    примитивных функций не поддерживает ширину, так без того, чтобы использовать pline () было бы необходимо генерировать много параллельных дуги и доли линии, чтобы моделировать заполненную дугу или долю линии с шириной. Это - неэффективный, и надлежащий дисплей,  зависим от вида (усиление).

    Получение ID объекта

    Через ID Вы можете получить указатель на фактический объект базы данных для обеспечения исполнения операций с ним. Для примера, см. “Открытие и Закрытие ObjectARX Объекты” на странице 27.
    Вы можете получить ID объекта несколькими способами:
    ·
    Создание объекта и добавление его в конец базы данных. База данных тогда дает объекту ID и возвращает его Вам.
    · Используют протокол базы данных для получения ID объектов, которые созданы автоматически, когда база данных создана (типа фиксированного набора таблиц идентификаторов и названного объектного словаря).
    · Используют класс - определенный протокол для получения объекта IDs. Некоторые классы, типа таблиц идентификаторов и словарей, определяют объекты, которые имеют другие объекты. Эти классы обеспечивают протокол для получения объекта IDs находящихся в собственности объектов.
    · Используют iterator, чтобы шагнуть через список или устанавить объект. AcDb библиотека обеспечивает множество iterators, которые могут использоваться, чтобы шагнуть через различные виды контейнерных объектов (AcDbDictionaryIterator, AcDbObjectIterator).
    · Сделать запрос набору выборов. После того, как пользователь выбрал объект, Вы можете спрашивать, чтобы  набор выборов для списка имен объекта выбранных объектов, и от имен, преобразовал к объекту IDs. Для получения дополнительной информации на selectionsets, см. главу 6, “Объекты”.

    Получение ID Объектного Реактора

    Каждый объект базы данных обслуживает{*поддерживает*} список реакторов на себе. Некоторые - переходные реакторы, и некоторые постоянны. Переходные реакторы - образцы классов, полученных из AcDbObjectReactor, принимая во внимание, что постоянные реакторы - объект IDs объектов резидента базы.
    Следующий код показывает, как перерыть список реакторов, чтобы найти ваш переходный или постоянный реактор. Чрезвычайно важно, что Вы проверяете специфический вход в реакторном списке, чтобы быть постоянным реактором,  используя функцию AcDbIsPersistentReactor. Если это - постоянный реактор, Вы можете использовать соответствующую функцию, чтобы получить ее объект ID. Если это - не постоянный реактор, Вы можете приводить вход в AcDbObjectReactor.
    AcDbVoidPtrArray *pReactors;
    void *pSomething;
    AcDbObjectReactor *pObjReactor;
    AcDbObjectId persObjId;
    AcDbObject *pPersReacObj;
    pReactors = pEnt->reactors();
    if (pReactors != NULL && pReactors->length() > 0) {
    for (int i = 0; i < pReactors->length(); i++) {
    pSomething = pReactors->at(i);
    // Is it a persistent reactor?
    //
    if (acdbIsPersistentReactor(pSomething)) {
    persObjId = acdbPersistentReactorObjectId(pSomething);
    acutPrintf("\n\nPersistent reactor found.");
    // Echo the keyname to the user.
    //
    char *keyname = NULL;
    getPersReactorKey(keyname, persObjId);
    if (keyname) {
    acutPrintf("\nThis is the reactor named %s",keyname);
    free (keyname);
    }
    // Open it up and see if it’s one of ours. If it is,
    // fire the custom notification.
    //
    if ((retStat = acdbOpenAcDbObject(pPersReacObj, persObjId, AcDb::kForNotify))
    != Acad::eOk)
    {
    acutPrintf("\nFailure for"
    " openAcDbObject: retStat==%d\n",
    retStat);
    return;
    }
    AsdkPersReactor *pTmpPers;
    if ((pTmpPers = AsdkPersReactor::cast((AcRxObject*)
    pPersReacObj)) != NULL)
    {
    pTmpPers->custom();
    }
    pPersReacObj->close();
    } else {
    // Or is it transient?
    //
    pObjReactor = (AcDbObjectReactor *)
    (pReactors->at(i));
    acutPrintf("\n\nTransient Reactor found");
    // Report what kind we found.
    //
    if (pObjReactor->isKindOf(
    AsdkSimpleObjReactor::desc()))
    {
    acutPrintf(" of type"
    " AsdkSimpleObjReactor");
    } else if (pObjReactor->isKindOf(AcDbEntityReactor::desc()))
    {
    acutPrintf(" of type"
    " AcDbEntityReactor");
    } else if (pObjReactor->isKindOf(AcDbObjectReactor::desc()))
    {
    acutPrintf(" of type"
    " AcDbObjectReactor");
    } else {
    acutPrintf(" of unknown type.");
    }
    }
    }
    } else {
    acutPrintf("\nThis entity has no reactors.\n");
    }

    Получение указателей на объекты в транзакции

    И AcTransactionManager:: getObject () и AcTransaction:: getObject () может использоваться, чтобы получить объектные указатели от объекта IDs. Указатели, таким образом полученные связаны с самой современной транзакцией. Попытка получить указатель, используя любых других операционных результатов по ошибке. Также, указатели, таким образом полученные имеют силу до транзакции они связаны с, или одна из содержащих транзакций, прерван. Когда наиболее удаленные операционные концы, изменения{*замены*} на всех имеющих силу указателях до того момента совершены{*переданы*}.
    Оба из getObject () функции берут параметр типа AcDb:: OpenMode, и Вы можете получить объектный указатель для чтения, записывать, или уведомлять.
    Все эти запросы преуспевают если бы не один случай: если объект уведомляет, и запрос должен получить указатель для записи (то есть с намерением изменения этого), ошибка (eWasNotifying) возвращена. Объект не должен измениться, в то время как это уведомляет другие относительно его состояния.
    Если Вы используете getObject () функция, чтобы получить объектный указатель, Вы никогда не должны вызвать близко () на том объектном указателе. Запрос близко () имеет силу только, если Вы получили указатель, используя acdbOpenObject () или объект был недавно создан. Для подробной информации на том, когда Вы можете вызывать близко () на объектном указателе, см. следующие секции, “ Недавно Созданные Объекты и транзакции ” и “ Смешивание Модели Транзакции с Открытым и Близким Механизмом. ”

    Постоянные AcGe примитивы

    Этот раздел описывает классы, имел обыкновение обеспечивать инерцию для AcGe примитивов, и иллюстрирует выполнение инерции. Три класса используются, чтобы обеспечить инерцию для AcGe
    примитивов: AcGeFiler, AcGeLibVersion, и AcGeFileIO.
    AcGeFiler - абстрактный класс, формирующий интерфейс для требований преобразования в последовательную форму AcGe. Пользователь должен обеспечить выполнение, полученное из AcGeFiler. В частности читая и пишущий внешних примитивов, и всех поверхностей кроме AcGePlane, требуют dwgFiler () функция на AcGeFiler, который будет осуществлен.
    AcGeLibVersion формирует версию AcGe. Это поддержано системой.
    Пользователь AcGe следит за версией AcGe,  используемого через глобальную переменную, AcGe:: gLibVersion. Все записи и читают AcGe примитивов,  выполнены в контексте версии используемого AcGe. Как правило, пользователь должен записать AcGe:: gLibVersion к файлу перед записью любого другого AcGe примитива (соответственно, это было бы первое чтение объекта AcGe от файла в последующем чтении). Следующие функции используются, чтобы записывать и читать этот объект (также см. следующее обсуждение AcGeFileIO класса):
    Acad::ErrorStatus outFields (AcGeFiler*, const AcGeLibVersion&)
    Acad::ErrorStatus inFields (AcGeFiler*, AcGeLibVersion&)
    Функции I/O файла AcGe примитивов - scoped в пределах AcGeFileIO класса.
    Они - коллекция статических функций для чтения и записи AcGe
    примитивов.

    Постоянство Данных Диалога

    CAcUiDialog и классы CACUITAB автоматически наследуют постоянство. Постоянство, как определено диалогами и средством управления в AcUi15.dll, означает, что память{*хранение*} для любого и всего пользователя модальные диалоги в AutoCAD, полученном из этих классов сохранит данные с текущим параметром пользователя, делая это виртуальное предпочтение.
    Ваш диалог должен иметь уникальное имя, потому что это будет использовать общедоступную область пространства{*пробела*} системного реестра параметра пользователя. Учитывая, что разработчики обычно создают их приложения, использующие их зарегистрированный префикс разработчика, следующий метод рекомендуется:
        Module-name:dialog-name
    Например, если бы ваше ObjectARX-приложение названо AsdkSample, и Вы имеете диалог названные Координаты, Вы назвали бы это AsdkSample:Coordinates.
    Имеются два типа постоянства данных диалога: из -the-box и определенный разработчиком.
    Из -the-box постоянства обращается{*относится*} к позиции диалога, размеру, и размерам столбца представления{*вида*} списка. Определено разработчиком обращается{*относится*} к любым данным, которые разработчик выбирает сохранять в параметре пользователя или в течение срока службы{*продолжительности жизни*} или смещения диалога и который может быть восстановлен{*отыскан*} поперек обращений диалога.

    Построение заказного диалога с табуляторами, расширяемого

    Создайте ваш табулированный диалог, используя CAcUiTabMainDialog для основной структуры{*рамки*} диалога и CACUITABCHILDDIALOG для каждой позиции табуляции. В OnInitDialog () или конструкторе CACUITABMAINDIALOG немедленно вызывают SetDialogName () с изданным именем вашего расширяемого диалога. ObjectARX-приложения будут использовать это имя, чтобы добавить позиции табуляции к вашему диалогу. После того, как Вы добавляете, что ваши позиции табуляции с звонят к AddTab (), в OnInitDialog, вызывать AddExtendedTabs (). Помните, что ваш табулированный диалог может иметь любое число добавленных позиций табуляции в этом, так что не примите установленное число позиций табуляции в другом месте в коде диалога.
    Например
    BOOL CPrefTabFrame:: OnInitDialog ()
    // Инициализация Диалога для моей табулированной структуры{*рамки*} диалога.
    {
    SetDialogName
    ("Предпочтение");
    CAcUiTabMainDialog:: OnInitDialog ();
    ...
    // Добавить мои позиции табуляции здесь.
     m_tab.AddTab(0,IDS_FILES_TABNAME,IDD_FILES_TAB,&m_filesTab);
     m_tab.AddTab(1,IDS_PERF_TABNAME,IDD_PERF_TAB,&m_performTab);
     m_tab.AddTab(2,IDS_COMP_TABNAME,IDD_COMP_TAB,&m_compatTab);
    // Добавить любые расширенные{*продленные*} позиции табуляции. Этот запрос состоит в том то, что делает это
    // Расширяемая позиция табуляции диалога
    AddExtendedTabs ();
    }

    Поверхности

    Ориентацию поверхности частично определяют ее оцененные нормальные векторы.
    Параметрическая поверхность имеет два параметра, u и v, каждое представляет  направление параметрических линий на поверхности. Если Вы берете векторное произведение u касательного вектора и v касательного вектора в той же самой точке, Вы получаете вектор, который является нормальным к поверхности. Этот вектор - естественная нормаль поверхности в той точке. Вы можете полностью изменять ориентацию поверхности,  вызывая следующую функцию:
    AcGeSurface&
    AcGeSurface::reverseNormal()
    Поверхностный вычислитель возвращает или естественную нормаль или ее инверсию, в зависимости от того, был ли reverseNormal () вызван четный или нечетное число времен. Следующая функция возвращает значение "ИСТИННО", если ориентация поверхности - напротив естественной ориентации:
    Adesk::Boolean
    AcGeSurface::isNormalReversed() const
    Этот пример создает круг и проектирует это на план XY. Тип проектируемого примитива тогда проверен, чтобы видеть какой примитив, в который это проектировалось:
    AcGePlane plane; // Constructs XY-plane.
    AcGePoint3d p1(2,3,5);
    AcGeVector3d v1(1,1,1);
    AcGeCircArc3d circ (p1, v1, 2.0);
    AcGeEntity3d *projectedEntity = circ.project(plane,v1);
    if (projectedEntity->type() == AcGe::kEllipArc3d)
    ...
    else if (projectedEntity->type() == AcGe::kCircArc3d)
    ...
    else if (projectedEntity->type() == AcGe::kLineSeg3d)
    ...
    Следующий пример создает НЕОДНОРОДНЫЙ РАЦИОНАЛЬНЫЙ В-СПЛАЙН, изгибают, и находит самую близкую точку на кривой к сути p1. Самая близкая точка возвращена как объект AcGePointOnCurve3d, от которого координаты и значение параметра получены:
    AcGeKnotVector knots;
    AcGePoint3dArray cntrlPnts;
    AcGePointOnCurve3d pntOnCrv;
    AcGePoint3d p1(1,3,2);
    knots.append (0.0);
    knots.append (0.0);
    knots.append (0.0);
    knots.append (0.0);
    knots.append (1.0);
    knots.append (1.0);
    knots.append (1.0);
    knots.append (1.0);
    cntrlPnts.append (AcGePoint3d(0,0,0));
    cntrlPnts.append (AcGePoint3d(1,1,0));
    cntrlPnts.append (AcGePoint3d(2,1,0));
    cntrlPnts.append (AcGePoint3d(3,0,0));
    AcGeNurbCurve3d nurb (3, knots, cntrlPnts);
    nurb.getClosestPointTo(p1,pntOnCrv);
    p2 = pntOnCrv.point();
    double param = pntOnCrv.parameter();

    Повторение

    Фильтры Точки ввода и мониторы могут быть вызваны множественные времена для единственной точки ввода при следующих условиях:
    §
    когда КЛАВИША ТАБУЛЯЦИИ нажата после события движения цифрового преобразователя, объектный поспешный кандидат на позицию курсора циклически повторяется. Как только движение курсора обнаружено, объектный поспешный кандидат, циклически повторяющий индекс сброшен.
    § когда зарегистрированный фильтр точки ввода возвращает индикацию Булевой переменной, чтобы повторить для точки, системные подсказки для нового события, не возвращение точка от события которое будет повторено.

    Повторно неиспользуемые команды AutoCAD

    Некоторые команды AutoCAD неповторно используемы. Они - команды, которые просят о вводе пользователя и поэтому обычно позволили бы выключатель окна документа, но вызовут серьезные осложнения, если это было переключено, или если команда была вызвана{*названа*} снова в другом документе. Три команды соответствуют эту конфигурацию:
    n TABLET
    n NEW
    n OPEN
    Команда TABLET ограничена, потому что пользователь определяет, как устройство управления позицией собирается работать, так, чтобы операция была должна быть закончена прежде, чем что - нибудь еще может быть сделано. Поскольку НОВЫЙ и ОТКРЫТЫЙ должны открыть окно, и затем просить о имени (когда FILEDIA=0), переключая к другому окну в тот момент мог быть подвержен ошибкам.

    Предложения конфигурации

    ObjectDBX клиентское приложение может выбирать один из следующих методов отобразить содержание DWG
    file:
    §
    Приспосабливают снабженный SimpleView библиотечный источник к использованию ведущими приложениями, и используют все три компонента. Изучение и приспосабливается, любой код от ViewAcDb производит выборку приложения как необходимо. Это - вероятно лучший способ статься знакомым с использованием AcGix и SimpleView AcGix
    выполнение платформы. Однако, Вы свободны изменить SimpleView источник как желательно.
    § Формируют модуль, чтобы управлять желательной графической системой через AcGix библиотеку. Это позволяет многое из существующей логики разработки многократно использоваться и все еще предлагает значительную гибкость в фактической сопроводительной графике и выполнении. Это вовлекло бы использование AcGix модуля, но записи выполнения AcGiViewport и AcGixVectorTaker на пустом месте, в действительности замена SimpleView и-или WhipView библиотек полностью.
    § Используют WhipView подсистему, чтобы сохранить элементы SimpleView, необходимого, чтобы поддержать определение AcGixBlockView. Это включает снабженную комбинацию WHIP! И HEIDI DLLs. Прямое использование WHIP! И HEIDI компоненты не поддержаны в этом выпуске.
    § Записывают,  полное заказное выполнение AcGi
    связывает с помощью интерфейса и не использует никакой из снабженного AcGix, SimpleView, или WhipView компонентов. Вы можете достигать максимального выполнения этот путь с максимальным количеством работы развития.

    Преобразования Системы координат

    AcedTrans () функция транслирует точку или смещение от одной системы координат в другой. Требуется параметр точки, запятая, которая может интерпретироваться или как трехмерная точка или трехмерный вектор смещения. Это управляется параметром, вызвал disp, который должен быть отличный от нуля, если с запятой обращаются как вектор смещения; иначе, с запятой обращаются как точка. Оттранслированная точка или вектор возвращены в параметре результата " передача параметра по ссылке ", который, подобно запятой, имеют тип ads_point.
    Параметры, которые определяют эти две системы координат, от и до, являются обоими буферами результатов. От параметра определяет систему координат, в которой запятая выражена, и к параметру определяет систему координат результата. И от и до параметр может определить систему координат следующим способом:
    § целочисленный код (restype == RTSHORT) который определяет WCS, текущий UCS, или текущий DCS (или текущей области просмотра или пространства листа).
    § имя примитива (restype == RTENAME), как возвращено одним имени примитива или выбора устанавливают функции. Это определяет ECS названного примитива. Для плоских примитивов, ECS может отличиться от WCS. Если ECS не отличается, преобразование между ECS и WCS - операция тождества.
    § трехмерный вектор вытеснения (restype == RT3DPOINT), который является другим методом определения ECS примитива. Векторы Вытеснения всегда представляются в мировых координатах; вектор вытеснения (0,0,1) определяет WCS непосредственно.
    Следующее - описания систем координат AutoCAD, которые могут быть определены от и до параметров.


    WCS

     Мировая система координат. Система координат “ссылки”. Все другие системы координат определены относительно WCS, который никогда не изменяется. Значения, измеренные относительно WCS устойчивы поперек изменений{*замен*} к другим системам координат.

    UCS

    Система координат Пользователя. “Рабочая” система координат. Все точки прошли к AutoCAD, командует, включая возвратился от подпрограмм AutoLISP и внешних функций, - точки в текущем UCS (если пользователь не предшествует им с * в Приглашении ко вводу команды). Если Вы хотите, чтобы ваше приложение послало координаты в WCS, ECS, или DCS к AutoCAD командует, Вы должны сначала преобразовать их к UCS,  вызывая acedTrans ().

    ECS

    Система координат Примитива. Значения Точки, возвращенные acdbEntGet () выражены в этой системе координат относительно примитива непосредственно. Такие точки бесполезны, пока они не преобразованы{*конвертированы*} в WCS, текущий UCS, или текущий DCS, согласно предназначенному использованию примитива. Наоборот, точки должны быть оттранслированы в ECS прежде, чем они написаны к базе данных посредством acdbEntMod () или acdbEntMake ().

    DCS

    Система координат Дисплея. Система координат, в которую объекты преобразованы прежде, чем они отображены. Начало координат DCS - точка, сохраненная в переменной ЦЕЛЕВОЙ СИСТЕМЫ AutoCAD, и ее Z ось - направление рассмотрения. Другими словами, область просмотра - всегда представление{*вид*} плана его DCS. Эти координаты могут использоваться, чтобы определить, где кое-что появляется пользователю AutoCAD. Когда от и до целочисленных кодов - 2 и 3, в любом порядке, 2 указывает, что  DCS для текущей области просмотра пространства модели, и 3 указывает DCS для пространства листа (PSDCS). Когда этот код 2 используется с целым числом, закодируют другой чем 3 (или другие средства определения системы координат), принято указать DCS пространства потока (пространство листа или пространство модели), и другой параметр принят, чтобы указать систему координат в текущем пространстве.

    PSDCS

    DCS Пространства листа. Эта система координат может быть преобразована только к или от DCS в настоящее время активной области просмотра пространства модели. Это - по существу 2-ое преобразование, где X и координаты Y всегда масштабируются и смещены, если disp параметр - 0. Координата Z масштабируется, но никогда не оттранслирована; это может использоваться, чтобы найти коэффициент масштаба между этими двумя системами координат. PSDCS (целое число закодируют 2) может быть преобразован только в текущую область просмотра пространства модели: если от параметра равняется 3, к параметру должен равняться 2, и наоборот.

    Следующий пример транслирует точку с WCS в текущий UCS.
    ads_point pt, result;
    struct resbuf fromrb, torb;
    pt[X] = 1.0;
    pt[Y] = 2.0;
    pt[Z] = 3.0;
    fromrb.restype = RTSHORT;
    fromrb.resval.rint = 0; // WCS
    torb.restype = RTSHORT;
    torb.resval.rint = 1; // UCS
    // disp == 0 indicates that pt is a point:
    acedTrans(pt, &fromrb, &torb, FALSE, result);
    Если текущий UCS вращается на 90 градусов против часовой стрелки во всем мире Z ось, запрос к acedTrans() устанавливают результат к сути (2.0, -1.0,3.0).
    Однако, если acedTrans() вызван, как показано в следующем примере, результат - (-2.0,1.0,3.0).
    acedTrans(pt, &torb, &fromrb, FALSE, result);

    Преобразования

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

    Графический конвейер может применять три возможных преобразования к примитиву:
    §
    блочные преобразования примитива
    § преобразование взгляда области просмотра
    § перспективное преобразование (если перспектива позволяется от DVIEW)
    Каждое преобразование производит новый тип координат, как показано в следующем рисунке. Если не в перспективном режиме, глаз и координаты дисплея идентичен.
    Преобразования
     (фронтальное  и заднее отсечение выполнено здесь если определено)
    Для REGEN, HIDE, и SHADE команд, мировые координаты примитива посланы через графический конвейер, показанный в числе{*рисунке*} выше. Преобразование представления{*вида*} определяет специфическое представление{*вид*} мировых координат, аналогичных рассмотрению сцены с камерой. Камера имеет местоположение в мировом пространстве{*пробеле*} и специфической ориентации к мировой координате “сцена”.
    Когда преобразование представления{*вида*} полно, мировые координаты преобразованы к координатам глаза, смотрящим вниз Z оси камеры.
    Если перспектива позволяется, координаты глаза преобразованы, чтобы отобразить координаты.
    Это преобразование возводит в степень раздел{*деление*} согласно тому, как далеко кое-что является от камеры, так, чтобы объекты дальше далеко от камеры казались меньшими чем объекты ближе на камеру.
    Следующие разделы обсуждают эти системы координат в большей подробности.

    Прерывания от пользователя

    Функции ввода пользователя и acedCommand (), acedCmd (), acedEntSel (), acedNEntSelP (), acedNEntSel (), acedDragGen (), и acedSSGet () функции возвращают RTCAN, если пользователь AutoCAD отвечает,  нажимая ESC. Внешняя функция должна обращаться с этим ответом как запрос отмены задания и возвращение немедленно.
    ObjectARX также обеспечивает функцию, acedUsrBrk (), это явно проверяет{*отмечает*}, нажал ли пользователь ESC. Эта функция позволяет приложениям ObjectARX проверить прерывание пользователя.
    Приложение не должно вызвать acedUsrBrk () если это не исполняет длинное вычисление между взаимодействиями с пользователем. Функция acedUsrBrk () никогда не должна использоваться как замена{*заместитель*} проверки значения, возвращенного функциями ввода пользователя, которые могут возвращать RTCAN.
    В некоторых случаях, приложение будет хотеть игнорировать запрос отмены пользователя. Если дело обстоит так, это вызвало acedUsrBrk () чтобы очистить запрос; иначе, ESC будет все еще невыполненный{*выдающийся*} и вызовет следующий запрос ввода пользователя терпеть неудачу. (Если приложение игнорирует ESC, это должно печатать сообщение, чтобы сообщить пользователю, которого это делает так.) Всякий раз, когда ObjectARX-приложение вызвано, условие ESC автоматически очищено.
    Например, следующий кодовый фрагмент терпит неудачу, если пользователь вводит ESC в подсказку.
    int test()
    {
    int i;
    while (!acedUsrBrk()) {
    acedGetInt("\nInput integer:", &i); // WRONG
    .
    .
    .
    }
    }
    Слегка изменяемый кодовый фрагмент, который следует правильно за метками ввод ESC без того, чтобы вызвать acedUsrBrk ().
    int test()
    {
    int i;
    for (;;) {
    if (acedGetInt("\nInput integer:", &i) != RTNORM)
    break;
    ...
    }
    }
    Следующая выборка изменяет{*заменяет*} условие цикла. Это строительство также работает правильно.
    int test()
    {
    int i;
    while (acedGetInt("\nInput integer:", &i) == RTNORM) {
    ...
    }
    }
    Имеющее силу место, чтобы использовать acedUsrBrk () находится в длинной операции. Например, код, который шагает через каждый примитив в базу данных рисунка, может быть потребление времени и должен вызвать acedUsrBrk ().

    Прикладное Имя

    Вся информация потребности Дизайн-центра AutoCAD от довольного средства доступа, участвующего в его заказном режиме сохранена под этой ключом. Имя ключа было бы имя приложения, поскольку это появляется в заказном режиме.
    Под ключом Application Name может быть следующие дополнительные клавиши:
    §
    Расширения
    Это содержит список расширений что довольные поддержки средства доступа (типа .dwg). Каждый ключ под расширениями представляет одно расширение. Имя ключа - имя расширения.
    § Средство поиска
    Этот ключ необязатен. Если приложение хочет участвовать в находящихся функциональных возможностях, то это требовано, чтобы заполнить этот ключ.
    Следующие значения системного реестра демонстрируют ветви системного реестра приложений:
    [HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R15.0\ACAD-x:
    xxx\AutodeskApps\AcadDC\Applications\Autodesk\Finder\Drawings]
    "LocalName"="Drawings"
    "File Based Search"=dword:00000001
    "Advanced Search"=dword:00000001
    "Date Search"=dword:00000001
    "Date Available"=dword:00000001
    "Size Available"=dword:00000001
    "Extension"=".dwg"
    "Auto Append"=dword:00000001
    [HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R15.0\ACAD-x:
    xxx\AutodeskApps\AcadDC\Applications\Autodesk\Finder\Drawings
    \Advanced Properties]
    "Advanced Property1"="Block name"
    "Advanced Property2"="Block and drawing description"
    "Advanced Property3"="Attribute tag"
    "Advanced Property4"="Attribute value"
    [HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R15.0\ACAD-x:
    xxx\AutodeskApps\AcadDC\Applications\Autodesk\Finder\Drawings
    \Properties]
    "Property1"="File Name"
    "Property2"="Title"
    "Property3"="Subject"
    "Property4"="Author"
    "Property5"="Keywords"

    A. Перемещение ADS программ к ObjectARX

    Чтобы упростить перемещение приложений AutoCAD development system к среде программы ObjectARX, библиотека ADS была перенесена к среде программы ObjectARX. ObjectARX версия почти идентична версии ADS. Это приложение обеспечивает сравнение того, как программы загружены, и в ADS и ObjectARX, и включает типовую программу, которая была перенесена от ADS до ObjectARX.
    §
    Перемещающий к ObjectARX
    § Загрузка Приложений: ADS против ObjectARX
    § Формирование ADS Приложения в Среде Программы ObjectARX
    § Типовое ObjectARX-приложение
    § ObjectARX-эксклюзивный Тип данных

    B. Программируемые Диалоговые окна

    ObjectARX содержит набор функций, который все вместе вызван Программируемое Диалоговое окно (PDB) пакет. PDB функции определяют средство управления диалогового окна, функциональные возможности, и соединение к приложению.
    Эта глава описывает, как использовать PDB. См. ObjectARX Ссылку для резюме и каталога функций, упомянутых в этой главе. Для руководящих принципов проекта диалогового окна, см. Руководство Настройки AutoCAD.
    Для информации относительно использования см  главы 8, “ MFC
    Темы.”
    §
    Краткий обзор
    § Иерархическая структура
    § Определения и Объявления
    § Обработка Неперекрывающих расположений

    Примера

    Следующие функции орудий приложения примера, которые называются
    Когда приложение загружено и разгруженный. Его функция инициализации добавляется
    Две новых команды к AutoCAD: СОЗДАЙТЕ и ВЫПОЛНИТЬ ИТЕРАЦИИ. Это также инициализирует Новый класс AsdkMyClass и прибавляет это к ObjectARX иерархии с
    AcrxBuildClassHierarchy () функция (. AsdkMyClass описан в “ Пример Заказного Объектного Класса ” на странице 338.)
    // Функция инициализации, называемая от acrxEntryPoint ()
    // Функция в течение kInitAppMsg случая{*регистра*} используется, чтобы прибавить команды
    // К команде располагают в стеке и прибавлять классы к ACRX классу
    // Иерархия.
    //
    void
    initApp()
    {
    acedRegCmds->addCommand("ASDK_DICTIONARY_COMMANDS",
    "ASDK_CREATE", "CREATE", ACRX_CMD_MODAL,
    createDictionary);
    acedRegCmds->addCommand("ASDK_DICTIONARY_COMMANDS",
    "ASDK_ITERATE", "ITERATE", ACRX_CMD_MODAL, iterateDictionary);
    AsdkMyClass::rxInit();
    acrxBuildClassHierarchy();
    }
    // Функция очистки, называемая от acrxEntryPoint ()
    // Функция в течение kUnloadAppMsg случая{*регистра*} удаляет это приложение
    // Команда сходит с команды, располагают в стеке, и удаляет это приложение
    // Заказные классы от ACRX иерархии классов во время выполнения.
    //
    void
    unloadApp()
    {
    acedRegCmds->removeGroup("ASDK_DICTIONARY_COMMANDS");
    // Удалить AsdkMyClass класс с ACRX времени выполнения
    // Иерархия классов. Если это сделано, в то время как база данных
    // Все еще активный, это должно вызвать все объекты{*цели*} класса
    // AsdkMyClass, чтобы быть превращен в proxies.
    //
    DeleteAcRxClass (AsdkMyClass:: desc ());
    }

    Приложения Загрузки: ADS против ObjectARX

    Загрузка Приложения в среде программы ObjectARX более гибка чем в среде программы ADS. В среде программы ADS, приложение ADS
    всегда остается в памяти.
    И в ObjectARX и средах программы ADS, приложение может быть загружено автоматически, когда AutoCAD вызван, если прикладное имя перечислено в acad.rx или acad.ads, соответственно.
    В среде программы ObjectARX, некоторые приложения, типа Выполняют, могут быть вызваны, когда одна из ее функций вызвана{*названа*}. Эта возможность сохраняет память для больших приложений подобно, выполняют, потому что это загружает приложение только в течение короткого времени в течение сессии рисунка.
    ObjectARX и загрузка приложения ADS
    отличен следующими способами:
    §
    когда рисунок закрыт или когда другой рисунок открыт, ObjectARX-приложения не разгружены. ObjectARX-приложение разгружено, когда AutoCAD закончен или когда приложение не имеет никаких иждивенцев и acedArxUnload () или эквивалентная функция вызвана{*названа*}.
    § В среде программы ObjectARX, рисунок присутствует, когда или kLoadDwg или kUnloadDwg сообщения или оба получены. Эти сообщения получены в случае цикл, когда или ADS или ObjectARX-приложение инициализирован или разгружен.
    § В среде программы ADS, рисунок присутствует, когда kInitAppMsg или kUnloadAppMsg получены.
    ОБРАТИТЕ ВНИМАНИЕ В среде программы ObjectARX, не предположите, что рисунок присутствует, когда kInitAppMsg или kUnloadAppMsg получены.
    § В среде программы ObjectARX, вызовите (arxload) или acedArxLoad () чтобы загрузить приложения. В среде программы ADS, вызовите (xload) или ads_xload () чтобы загрузить приложения.
    § ObjectARX-приложения, перечисленные в acad.rx загружены автоматически, когда AutoCAD вызван, и в отличие от приложений ADS, приложения ObjectARX инициализированы прежде, чем рисунок присутствует и прежде, чем ADS или Визуальные среды LISP инициализирован. В среде программы ADS, коллега{*копия*} acad.rx - acad.ads. Поместите названия{*имена*} модулей прикладных программ в соответствующем файле, одно имя в линию.

    Примечания относительно Расширенных Данных

    Несколько функций ObjectARX обеспечиваются, чтобы обработать расширенные данные. Расширенные данные примитива следуют за нормальными данными определения примитива. Это иллюстрировано следующим рисунком, которое показывает схеме списка буфера результата для примитива, содержащего расширенные данные.
    Расширенные данные примитива могут быть отысканы,  вызывая acdbEntGetX (), который является подобным acdbEntGet (). AcdbEntGetX () функция отыскивает нормальные данные определения примитива и расширенные данные для приложений, указанных в acdbEntGetX () запрос.
    ОБРАТИТЕ ВНИМАНИЕ, когда расширенные данные отысканы acdbEntGetX (), начало расширенных данных обозначено -3 кодом стража; -3 страж находится в буфере результатов, который предшествует первой 1001 группе. 1001 группа содержит прикладное имя первого отысканного приложения, как показано в рисунке.
    Примечания относительно Расширенных Данных
    Организация Расширенных Данных
    Расширенные  данные состоят из одного или большее количество 1001 групп, каждая из которых начинается с уникального прикладного имени. Прикладные названия - строковые значения. Расширенные группы данных возвратились acdbEntGetX () следуют за данными определения в порядке, в котором они сохранены в базе данных.
    В пределах группы каждого приложения, содержания, значение, и организация данных определено приложением; AutoCAD поддерживает информацию, но не использует это. Коды Группы для расширенных  данных находятся в 1000-1071 диапазоне, следующим образом:

    Строка
    1000. Строки в расширенных данных могут быть до длиной 255 байтов (с 256-ым байтом, зарезервированным для нулевого символа).
    Прикладное имя
    1001 (также строковое значение). Прикладные названия могут быть до длиной 31 байтов (32-ой байт зарезервирован для нулевого символа) и должен твердо придержаться правил для названий таблицы идентификаторов (типа названий уровня). Прикладное имя может содержать символы, цифры, и специальные символы $ (долларовый признак), - (дефис), и _ (символ подчеркивания). Это не может содержать пробелы. Символы на имя преобразованы к верхнему регистру.
    <

    Системы координат

    Этот пример берет долю линии, определенную в модели, координирует и создает ее эквиваленты в координатах дисплея и глазе. Когда отображено, все линии наложатся.
    void
    AsdkCoordSamp::viewportDraw(AcGiViewportDraw* pV)
    {
    pV->subEntityTraits().setFillType(kAcGiFillAlways);
    const int count = 3;
    AcGePoint3d verts[count];
    verts[0] = AcGePoint3d(0.0, 0.0, 0.0);
    verts[1] = AcGePoint3d(1.0, 0.0, 0.0);
    verts[2] = AcGePoint3d(1.0, 1.0, 0.0);
    // Draw model space line segment.
    //
    pV->subEntityTraits().setColor(kBlue);
    pV->geometry().polygon(count, verts);
    // Compute the line’s representation in eye space.
    //
    AcGeMatrix3d mat;
    pV->viewport().getModelToEyeTransform(mat);
    for (int i = 0; i < count; i++) {
    verts[i].x += 0.01;
    verts[i].y += 0.01;
    verts[i].z += 0.01;
    verts[i].transformBy(mat);
    }
    // Display the eye coordinate equivalent of the
    // model space polygon.
    //
    pV->subEntityTraits().setColor(kGreen);
    pV->geometry().polygonEye(count, verts);
    // Convert from eye to display coordinates.
    //
    for (i = 0; i < count; i++) {
    verts[i].x += 0.01;
    verts[i].y += 0.01;
    verts[i].z += 0.01;
    }
    // Draw the display space equivalent of the
    // model space polygon.
    //
    pV->subEntityTraits().setColor(kRed);
    pV->geometry().polygonDc(count, verts);
    }

    Определение Невидимых линий для Объекта для Стандартного Дисплея

    Этот пример отображает пирамиду, показывая передние грани в желтом и обратные грани в синем, чтобы дать Вам идею относительно видимых и скрытых граней пирамиды. Пример показывает применение{*обращение*} преобразования " модель к глазу " и затем перспективное преобразование. Это использует координаты глаза, чтобы рисовать примитив и использование показов isPerspective (), doPerspective (), getFrontandBackClipValues (), polylineDc (), polylineEye () и polyline().
    Преобразовывать координату глаза выравнивают долю, чтобы отобразить пространство
    1 если вид имеет планы отсечения в силе, зажим доля линии координаты xглаза к ним.
    2 если перспектива включена, то, исполняет преобразование от координат глаза до перспективы.
    Если вы используете polygonEye (), polygonDc (), polylineEye (), или polylineDc () функции AcGiViewportGeometry, Вы должны вызвать AcGiWorldGeometry:: setExtents () чтобы установить поле ограничения для примитива. Это позволит AutoCAD знать, сколько пространства примитив требует и используется в ZOOM Степени. SetExtents () функция обычно вызвана, когда примитив находится в мировых координатах, чтобы определить самое маленькое поле, которое будет соответствовать вокруг примитива в мировых координатах.
    AsdkViewGeomSamp::AsdkViewGeomSamp() : mNumVerts(4)
    {
    mVerts[0] = AcGePoint3d(0.0, 0.0, 0.0);
    mVerts[1] = AcGePoint3d(1.0, 0.0, 0.0);
    mVerts[2] = AcGePoint3d(0.0, 1.0, 0.0);
    mVerts[3] = AcGePoint3d(0.0, 0.0, 1.0);
    }
    Acad::ErrorStatus
    AsdkViewGeomSamp::transformBy(const AcGeMatrix3d &xfm)
    {
    assertWriteEnabled();
    for (Adesk::UInt32 i = 0; i < mNumVerts; i++) {
    mVerts[i].transformBy(xfm);
    }
    return Acad::eOk;
    }
    Adesk::Boolean
    AsdkViewGeomSamp::worldDraw(AcGiWorldDraw* pW)
    {
    // Draw a pyramid.
    //
    // If this is the regular AutoCAD DISPLAY mode...
    //
    if (pW->regenType() == kAcGiStandardDisplay) {
    // From each viewport’s vantage point, figure out
    // which sides of the pyramid are visible,
    // then make the visible ones yellow and the hidden

    // ones blue.
    //
    // Set the extents of the pyramid here because
    // AcGiViewportGeometry’s polylineEye() doesn’t
    // set extents.
    //
    for (Adesk::UInt32 i = 0; i < mNumVerts; i++) {
    AcGePoint3d pt[2];
    pt[0] = mVerts[i];
    pt[1] = mVerts[(i + 1) % mNumVerts];
    pW->geometry().setExtents(pt);
    }
    return Adesk::kFalse; // Call viewport draws.
    }
    // Otherwise, give HIDE, SHADE, RENDER, or proxy graphics
    // a pyramid with filled faces.
    //
    const Adesk::UInt32 faceListSize = 16;
    static Adesk::Int32 faceList[faceListSize] = {
    3, 0, 1, 2,
    3, 0, 2, 3,
    3, 0, 3, 1,
    3, 1, 2, 3
    };
    pW->geometry().shell(mNumVerts, mVerts, faceListSize, faceList);
    return Adesk::kTrue; // Do not call viewportDraw.
    }
    void
    AsdkViewGeomSamp::viewportDraw(AcGiViewportDraw* pV)
    {
    // For this viewport, draw a pyramid with yellow
    // visible lines and blue hidden lines.
    //
    // Get this viewport’s net transform. This transform
    // includes this entity’s block transforms and this
    // viewport’s view transform; it does not include the
    // perspective transform if we’re in perspective
    // mode; that currently has to be applied separately
    // when in perspective mode.
    //
    AcGeMatrix3d modelToEyeMat;
    pV->viewport().getModelToEyeTransform(modelToEyeMat);
    // Get the pyramid’s vertices.
    //
    AcGePoint3d A = mVerts[0];
    AcGePoint3d B = mVerts[1];
    AcGePoint3d C = mVerts[2];
    AcGePoint3d D = mVerts[3];
    // Convert them to the viewport’s eye coordinates.
    //
    A.transformBy(modelToEyeMat);
    B.transformBy(modelToEyeMat);
    C.transformBy(modelToEyeMat);
    D.transformBy(modelToEyeMat);
    // Save the eye coordinates.
    //
    AcGePoint3d AEye = A;
    AcGePoint3d BEye = B;
    AcGePoint3d CEye = C;
    AcGePoint3d DEye = D;
    // Perform the perspective transform if necessary.
    //
    if (pV->viewport().isPerspective()) {
    pV->viewport().doPerspective(A);
    pV->viewport().doPerspective(B);
    pV->viewport().doPerspective(C);
    pV->viewport().doPerspective(D);
    }
    // From that view, figure out which faces are


    // facing the viewport and which are not.
    //
    int which_faces;
    which_faces = ((C - A).crossProduct(B - A)).z > 0.0 ? 1 : 0;
    which_faces |= ((D - A).crossProduct(C - A)).z > 0.0 ? 2 : 0;
    which_faces |= ((B - A).crossProduct(D - A)).z > 0.0 ? 4 : 0;
    which_faces |= ((B - D).crossProduct(C - D)).z > 0.0 ? 8 : 0;
    // Those edges that meet between two faces that are
    // facing away from the viewport will be hidden edges,
    // so draw them blue; otherwise, they are visible
    // edges. (This example is incomplete, as the test is
    // indeterminate when the face is edge-on to the
    // screen -- neither facing away nor toward the screen.)
    // Draw the six edges connecting the vertices using eye
    // coordinate geometry that can be clipped back and front.
    //
    AcGePoint3d verts[2];
    Adesk::UInt16 color;
    // AB
    color = which_faces & 0x5 ? kYellow : kBlue;
    pV->subEntityTraits().setColor(color);
    verts[0] = AEye;
    verts[1] = BEye;
    pV->geometry().polylineEye(2, verts);
    // AC
    color = which_faces & 0x3 ? kYellow : kBlue;
    pV->subEntityTraits().setColor(color);
    verts[0] = AEye;
    verts[1] = CEye;
    pV->geometry().polylineEye(2, verts);
    // AD
    color = which_faces & 0x6 ? kYellow : kBlue;
    pV->subEntityTraits().setColor(color);
    verts[0] = AEye;
    verts[1] = DEye;
    pV->geometry().polylineEye(2, verts);
    // CD
    color = which_faces & 0xa ? kYellow : kBlue;
    pV->subEntityTraits().setColor(color);
    verts[0] = CEye;
    verts[1] = DEye;
    pV->geometry().polylineEye(2, verts);
    // DB
    color = which_faces & 0xc ? kYellow : kBlue;
    pV->subEntityTraits().setColor(color);
    verts[0] = DEye;
    verts[1] = BEye;
    pV->geometry().polylineEye(2, verts);
    // BC
    color = which_faces & 0x9 ? kYellow : kBlue;
    pV->subEntityTraits().setColor(color);
    verts[0] = BEye;
    verts[1] = CEye;
    pV->geometry().polylineEye(2, verts);
    }

    Получение Координат Окна

    Этот пример показывает использование AcGiViewportDraw:: polylineDc () и AcGiViewport:: getViewportDcCorners () чтобы получить координаты дисплея области просмотра. Эта функция удобна, когда Вы рисуете графику, которые зависят от физического размещения области просмотра, типа значков и маркеров, которые изменяются с размером или границами области просмотра. Рисовавшая графика изменится с панорамированием и изменением масштаба изображения.
    Пример рисует поле в правом верхнем углу области просмотра. Ширина поля и высота - всегда десятая часть самого короткого измерения области просмотра, и поле центрировано десятая часть самого короткого измерения области просмотра вниз и налево от правого верхнего угла области просмотра:
    void
    AsdkIconSamp::viewportDraw(AcGiViewportDraw* pV)
    {
    // Get the current viewport’s display coordinates.
    //
    AcGePoint2d lower_left, upper_right;
    pV->viewport().getViewportDcCorners(lower_left, upper_right);
    double xsize = upper_right.x - lower_left.x;
    double ysize = upper_right.y - lower_left.y;
    xsize /= 10.0;
    ysize /= 10.0;
    double xcenter = upper_right.x - xsize;
    double ycenter = upper_right.y - ysize;
    double half_xsize = xsize / 2.0;
    double half_ysize = ysize / 2.0;
    // Create a unit square.
    //
    const int num_verts = 5;
    AcGePoint3d verts[num_verts];
    for (int i = 0; i < num_verts; i++) {
    verts[i].x = xcenter;
    verts[i].y = ycenter;
    verts[i].z = 0.0;
    }
    verts[0].x -= half_xsize;
    verts[0].y += half_ysize;
    verts[1].x += half_xsize;
    verts[1].y += half_ysize;
    verts[2].x += half_xsize;
    verts[2].y -= half_ysize;
    verts[3].x -= half_xsize;
    verts[3].y -= half_ysize;
    verts[4] = verts[0];
    pV->subEntityTraits().setColor(kRed);
    pV->geometry().polylineDc(num_verts, verts);
    }

    Вычисление Круга, чтобы Рисовать

    Следующий пример рисует круг модуля, центрированный в начале координат. Точный рисовавший круг зависит от взгляда области просмотра круга. Цель состоит в том, чтобы рисовать круг с полилинией, которая имеет минимальное число заметных долей. С командой VPORTS, Вы можете создавать четыре области просмотра и затем нажимать на один и раскрывать на круге, затем нажимать на другой и копировать от этого. Когда Вы REGENALL, каждая область просмотра вычисляет ее собственный минимально сегментированное представление полилинии круга.
    Это - то, как пример вычисляет необходимое число долей линии в полилинии. Сначала, учитывая круг данного радиуса, который центрирован в начале координат и расположен в XY плане, и дан вертикальную линию, которая пересекает X ось в радиусе - 0.5 пикселов, определять угол между X осью и долей линии, которая простирается от начала координат к сути, где вертикальная линия пересекает круг. Два pi разделенный этим углом обеспечивает минимальное число долей, необходимых полилинией, чтобы напомнить круг. Пользователь не будет способен дифференцировать индивидуальные доли линии, которые составляют круг, потому что визуальные различия - меньше чем пиксел.
    Вычисление Круга, чтобы Рисовать
    Adesk::Boolean
    AsdkTesselateSamp::worldDraw(AcGiWorldDraw *pW)
    {
    // Draw a red 1x1 drawing-unit square centered at the
    // world coordinate origin and parallel to the XY-plane.
    //
    const Adesk::UInt32 num_pts = 5;
    AcGePoint3d verts[num_pts];
    verts[0] = verts[4] = AcGePoint3d(-0.5, -0.5, 0.0);
    verts[1] = AcGePoint3d( 0.5, -0.5, 0.0);
    verts[2] = AcGePoint3d( 0.5, 0.5, 0.0);
    verts[3] = AcGePoint3d(-0.5, 0.5, 0.0);
    pW->subEntityTraits().setColor(kRed);
    pW->geometry().polyline(num_pts, verts);
    // If regenType is kAcGiSaveWorldDrawForProxy, return
    // Adesk::kTrue, otherwise return Adesk::kFalse to trigger
    // calls to viewportDraw().
    //
    return (pW->regenType() == kAcGiSaveWorldDrawForProxy);
    }
    void
    AsdkTesselateSamp::viewportDraw(AcGiViewportDraw *pV)
    {
    static double two_pi = atan(1.0) * 8.0;

    // Get the number of pixels on the X- and Y-edges of
    // a unit square centered at (0.0, 0.0, 0.0), in
    // world coordinates.
    //
    AcGePoint3d center(0.0, 0.0, 0.0);
    AcGePoint2d area;
    pV->viewport().getNumPixelsInUnitSquare(center, area);
    // If the area values are negative, then we are in
    // perspective mode and the center is too close or
    // in back of the viewport.
    //
    if (area.x > 0.0) {
    // Print out the number of pixels along the
    // Y-axis of the unit square used in
    // getNumPixelsInUnitSquare.
    //
    AcGeVector3d norm(0.0, 0.0, 1.0);
    AcGeVector3d dir(1.0, 0.0, 0.0);
    char buf[100];
    sprintf(buf, "%7.3lf", area.y);
    pV->geometry().text(center, norm, dir, 1.0, 1.0, 0.0, buf);
    // Draw a circle that depends on how big the circle
    // is in the viewport. This requires
    // figuring out the fewest number of segments needed
    // by a polyline so that it doesn’t look segmented.
    //
    // The worldDraw() and viewportDraw() of
    // an entity in a viewport are only called during a
    // regen and not necessarily during a ZOOM or PAN.
    // The reason is that a regen produces something
    // akin to a very high resolution image internally,
    // which AutoCAD can zoom in or pan around. That is,
    // until you get too close to this image or any of
    // its edges, at which point a regen is internally
    // invoked for that viewport and a new internal
    // image is created (ready to be mildly zoomed and
    // panned).
    //
    double radius = 0.5;
    double half_pixel_hgt = 2.0 / area.x; // In WCS
    int num_segs = 8;
    double angle = two_pi / num_segs;
    if (half_pixel_hgt > radius / 2) {
    // The circle is approximately the same or less
    // than the size of a pixel. So, generate a very
    // small octagon.
    //
    num_segs = 8;
    } else {
    // Given a circle centered at the origin of a
    // given radius in the XY-plane, and given a
    // vertical line that intersects the X-axis at
    // ’radius - half a pixel’, what is the angle
    // from the X-axis of a line segment from the
    // origin to the point where the vertical line


    // and the circle intersect? Two pi divided by
    // this angle gives you a minimum number of
    // segments needed by a polyline to look like
    // a circle and not be able to differentiate
    // the individual segments because the visual
    // differences are less than the size of a
    // pixel. (This is not the only way to figure
    // this out but it’s sufficient.)
    //
    angle = acos((radius - 1.0 / (area.x / 2.0)) / radius);
    double d_num_segs = two_pi / angle;
    // Limit the number of segments from 8 to
    // 128 and use whole numbers for
    // this count.
    //
    if (d_num_segs < 8.0) {
    num_segs = 8;
    } else if (d_num_segs > 128.0) {
    num_segs = 128;
    } else {
    num_segs = (int)d_num_segs;
    }
    }
    // Calculate the vertices of the polyline from the
    // start, around the circle, and back to the start
    // to close the polyline.
    //
    angle = 0.0;
    double angle_inc = two_pi / (double)num_segs;
    AcGePoint3d* verts = new AcGePoint3d[num_segs + 1];
    for (int i = 0; i <= num_segs; i++, angle += angle_inc)
    {
    verts[i].x = center.x + radius * cos(angle);
    verts[i].y = center.y + radius * sin(angle);
    verts[i].z = center.z;
    }
    pV->geometry().polyline(num_segs + 1, verts);
    delete [] verts;
    }
    }
    Использование Границ Обрезки в AcGi
    ObjectARX позволяет Вам определять границу отсечения для геометрии, содержащейся в пределах таблиц перекрестных ссылок и блоков. Часть границы обрезки AcGi API позволяет составные объекты (блоки и объекты, которые ведут себя подобно блокам) чтобы выразить эти границы обрезки AcGi выполнению.
    В течение worldDraw () или viewportDraw () любой drawable может определить многоугольную границу обрезки,  чтобы отсечь ее графику. Следующие разделы описывают, как использовать эту особенность API.

    Пример формирования зависимостей в объекте

    Следующий пример показывает, как Вы можете использовать реакторы, чтобы установить зависимости среди объектов базы данных. В этом примере, когда Вы изменяете одну линию, другие изменяются тоже.
    class AsdkObjectToNotify : public AcDbObject
    //
    // AsdkObjectToNotify - customized AcDbObject for persistent
    // reactor to notify.
    //
    {
    public:
    ACRX_DECLARE_MEMBERS(AsdkObjectToNotify);
    AsdkObjectToNotify() {};
    void eLinkage(AcDbObjectId i, double f=1.0)
    {mId=i; mFactor=f; };
    void modified(const AcDbObject*);
    Acad::ErrorStatus dwgInFields(AcDbDwgFiler*);
    Acad::ErrorStatus dwgOutFields(AcDbDwgFiler*) const;
    Acad::ErrorStatus dxfInFields(AcDbDxfFiler*);
    Acad::ErrorStatus dxfOutFields(AcDbDxfFiler*) const;
    private:
    AcDbObjectId mId;
    double mFactor;
    };
    ACRX_DXF_DEFINE_MEMBERS(AsdkObjectToNotify, AcDbObject,
    AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent,
    0, ASDKOBJECTTONOTIFY, persreac);
    // This function is called every time the line it’s
    // "watching" is modified. When it’s called, it opens the
    // other line of the pair and changes that line’s length to
    // match the new length of the line that’s just been
    // modified.
    //
    void
    AsdkObjectToNotify::modified(const AcDbObject* pObj)
    {
    AcDbLine *pLine = AcDbLine::cast(pObj);
    if (!pLine) {
    const char* cstr = pObj->isA()->name();
    acutPrintf("This is a %s.\n", cstr);
    acutPrintf("I only work with lines. Sorry.\n");
    return;
    }
    acutPrintf("\nReactor attached to %lx calling %lx.\n",
    pLine->objectId(), mId);
    // This open will fail during notification caused by a
    // reactor being added to the entity or when this
    // notification is in reaction to a change due to the
    // other line’s reactor changing this line. This will
    // properly prevent an infinite recursive loop
    // between the two lines and their reactors.
    //
    AcDbLine *pLine2;
    if (acdbOpenObject((AcDbObject*&)pLine2, mId, AcDb::kForWrite) == Acad::eOk)
    {
    // Get length of line entity we’re being notified

    // has just been modified.
    //
    AcGePoint3d p = pLine->startPoint();
    AcGePoint3d q = pLine->endPoint();
    AcGeVector3d v = q-p;
    double len = v.length();
    // update other entity to match:
    //
    p = pLine2->startPoint();
    q = pLine2->endPoint();
    v = q-p;
    v = len * mFactor * v.normal();
    pLine2->setEndPoint(p+v);
    pLine2->close();
    }
    }
    // Files an object’s information in.
    //
    Acad::ErrorStatus
    AsdkObjectToNotify::dwgInFields(AcDbDwgFiler* filer)
    {
    assertWriteEnabled();
    AcDbObject::dwgInFields(filer);
    filer->readItem(&mFactor);
    filer->readItem((AcDbSoftPointerId*) &mId);
    return filer->filerStatus();
    }
    // Files an object’s information out.
    //
    Acad::ErrorStatus
    AsdkObjectToNotify::dwgOutFields(AcDbDwgFiler* filer) const
    {
    assertReadEnabled();
    AcDbObject::dwgOutFields(filer);
    filer->writeItem(mFactor);
    filer->writeItem((AcDbSoftPointerId&)mId);
    return filer->filerStatus();
    }
    // Files an object’ s information in from DXF and AutoLISP.
    //
    Acad::ErrorStatus
    AsdkObjectToNotify::dxfInFields(AcDbDxfFiler* filer)
    {
    assertWriteEnabled();
    Acad::ErrorStatus es;
    if ((es = AcDbObject::dxfInFields(filer)) != Acad::eOk)
    {
    return es;
    }
    // Check if we’re at the right subclass data marker.
    //
    if(!filer->atSubclassData("AsdkObjectToNotify")) {
    return Acad::eBadDxfSequence;
    }
    struct resbuf rbIn;
    while (es == Acad::eOk) {
    if ((es = filer->readItem(&rbIn)) == Acad::eOk) {
    if (rbIn.restype == AcDb::kDxfReal) {
    mFactor = rbIn.resval.rreal;
    } else if (rbIn.restype == AcDb::kDxfSoftPointerId)
    {
    // ObjectIds are filed in as ads_names.
    //
    acdbGetObjectId(mId, rbIn.resval.rlname);
    } else { // invalid group
    return(filer->pushBackItem());
    }
    }
    }
    return filer->filerStatus();
    }
    // Files an object’s information out to DXF and AutoLISP.
    //
    Acad::ErrorStatus
    AsdkObjectToNotify::dxfOutFields(AcDbDxfFiler* filer) const
    {
    assertReadEnabled();
    AcDbObject::dxfOutFields(filer);


    filer->writeItem(AcDb::kDxfSubclass, "AsdkObjectToNotify");
    filer->writeItem(AcDb::kDxfReal, mFactor);
    filer->writeItem(AcDb::kDxfSoftPointerId, mId);
    return filer->filerStatus();
    }
    // Creates two lines and two AsdkObjectToNotify objects and
    // ties them all together.
    //
    void
    assocLines()
    {
    AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();
    AcDbObjectId aId, bId;
    AcDbLine *pLineA = new AcDbLine;
    pLineA->setDatabaseDefaults(pDb);
    pLineA->setStartPoint(AcGePoint3d(1, 1, 0));
    pLineA->setEndPoint(AcGePoint3d(2, 1, 0));
    addToModelSpace(aId, pLineA);
    acutPrintf( "Line A is %lx from 1,1 to 2,1.\n",
    pLineA->objectId());
    AcDbLine *pLineB = new AcDbLine;
    pLineB->setDatabaseDefaults(pDb);
    pLineB->setStartPoint(AcGePoint3d(1, 2, 0));
    pLineB->setEndPoint(AcGePoint3d(2, 2, 0));
    addToModelSpace(bId, pLineB);
    acutPrintf("Line B is %lx from 1,2 to 2,2.\n", pLineB->objectId());
    // Open the named object dictionary, and check if there is
    // an entry with the key "ASDK_DICT". If not, create a
    // dictionary and add it.
    //
    AcDbDictionary *pNamedObj;
    AcDbDictionary *pNameList;
    pDb->getNamedObjectsDictionary(pNamedObj, AcDb::kForWrite);
    if (pNamedObj->getAt("ASDK_DICT",
    (AcDbObject*&)pNameList, AcDb::kForWrite)
    == Acad::eKeyNotFound)
    {
    pNameList = new AcDbDictionary;
    AcDbObjectId DictId;
    pNamedObj->setAt("ASDK_DICT", pNameList, DictId);
    }
    pNamedObj->close();
    // Create the AsdkObjectToNotify for line A.
    //
    AsdkObjectToNotify *pObj = new AsdkObjectToNotify();
    pObj->eLinkage(bId);
    AcDbObjectId objId;
    if ((pNameList->getAt("object_to_notify_A", objId)) == Acad::eKeyNotFound)
    {
    pNameList->setAt("object_to_notify_A", pObj, objId);
    pObj->close();
    } else {
    delete pObj;
    acutPrintf("object_to_notify_A already exists\n");
    }
    // Set up persistent reactor link between line A


    // and AsdkObjectToNotify.
    //
    pLineA->addPersistentReactor(objId);
    pLineA->close();
    // Create the AsdkObjectToNotify for line B.
    //
    pObj = new AsdkObjectToNotify();
    pObj->eLinkage(aId);
    if ((pNameList->getAt("object_to_notify_B", objId)) == Acad::eKeyNotFound)
    {
    pNameList->setAt("object_to_notify_B", pObj, objId);
    pObj->close();
    } else {
    delete pObj;
    acutPrintf("object_to_notify_B already exists\n");
    }
    pNameList->close();
    // Set up persistent reactor link between line B
    // and AsdkObjectToNotify.
    //
    pLineB->addPersistentReactor(objId);
    pLineB->close();
    }
    // Adds an entity to model space, but does not close
    // the entity.
    //
    void
    addToModelSpace(AcDbObjectId &objId, AcDbEntity* pEntity)
    {
    AcDbBlockTable *pBlockTable;
    AcDbBlockTableRecord *pSpaceRecord;
    acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pBlockTable, AcDb::kForRead);
    pBlockTable->getAt(ACDB_MODEL_SPACE, pSpaceRecord,
    AcDb::kForWrite);
    pBlockTable->close();
    pSpaceRecord->appendAcDbEntity(objId, pEntity);
    pSpaceRecord->close();
    return;
    }
    // This is the initialization function called from acrxEntryPoint()
    // during the kInitAppMsg case. This function is used to add
    // commands to the command stack.
    //
    void
    initApp()
    {
    acedRegCmds->addCommand("ASDK_ALINES", "ASDK_ALINES",
    "ALINES", ACRX_CMD_MODAL, assocLines);
    AsdkObjectToNotify::rxInit();
    acrxBuildClassHierarchy();
    }
    // This is the clean-up function called from acrxEntryPoint() during
    // the kUnloadAppMsg case. This function removes this application’s
    // command set from the command stack.
    //
    void
    unloadApp()
    {
    acedRegCmds->removeGroup("ASDK_ALINES");
    // Remove the AsdkObjectToNotify class from the ACRX
    // runtime class hierarchy. If this is done while the
    // database is still active, it should cause all objects
    // of class AsdkObjectToNotify to be turned into proxies.
    //
    deleteAcRxClass(AsdkObjectToNotify::desc());
    }
    // ObjectARX entry point
    //
    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();
    }
    return AcRx::kRetOK;
    }

    Пример функции ObjectARX

    Следующая функция ObjectARX отображает пример:
    int showalert()
    {
    int dcl_id, dbstatus;
    ads_hdlg dbhello;
    // Load the DCL file.
    //
    ads_load_dialog("hello.dcl", &dcl_id);
    // Initialize the dialog.
    //
    if (ads_new_dialog("hello", dcl_id, NULLCB, &dbhello) != RTNORM) {
    acdbFail("Unable to initialize dialog box called
    \"hello\"\n");
    return BAD; // Exit if this does not work
    }
    // Associate an action. End expression with a key, in this
    // case, the OK button. End the dialog when OK is pressed.
    //
    ads_action_tile(dbhello, "accept", accept_OK);
    // Display the dialog box.
    //
    ads_start_dialog(dbhello, &dbstatus);
    ads_unload_dialog(dcl_id); // Unload the DCL file
    return GOOD;
    }
    static void CALLB accept_OK(ads_callback_packet *cpkt)
    {
    // DLGOK == User pressed OK
    //
    ads_done_dialog(cpkt->dialog, DLGOK);
    }
    После ads_start_dialog () запрос, диалоговое окно остается активным, пока пользователь не выбирает неперекрывающее расположение (обычно кнопка). Функция ads_action_tile () вызвана, и это вызывает функцию повторного вызова. Параметры к функции повторного вызова включены в отдельную структуру пакета повторного вызова. Повторный вызов вызывает ads_done_dialog ().
    Комплексное диалоговое окно требует, больше вызывает к ads_action_tile (), возможно другая инициализация вызывает, и вероятно большее количество ввода, обрабатывающего между ads_start_dialog () и ads_unload_dialog () вызывает. Полная последовательность запроса, тем не менее, остается тем же самый.

    Пример Гиперсвязи

    Следующая функция перечисляет гиперсвязи, связанные с примитивом и позволяет новым гиперсвязям быть добавленной в их месте. (Проверка ошибок не показывается.)
    void AddHyperlink()
    {
    ads_name en;
    ads_point pt;
    AcDbEntity * pEnt;
    AcDbObjectId pEntId;
    // Prompt user to select entity.
    acedEntSel("\nSelect an Entity: ", en, pt);
    // Get Object id.
    acdbGetObjectId(pEntId, en);
    // Open object for write.
    acdbOpenObject(pEnt, pEntId, AcDb::kForWrite);
    // The hyperlink collection object is created inside
    // of getHyperlinkCollection
    // below. It is our responsibility to delete it.
    AcDbHyperlinkCollection * pcHCL = NULL;
    // Get the hyperlink collection associated with the entity.
    ACRX_X_CALL(pEnt, AcDbEntityHyperlinkPE)->
    getHyperlinkCollection(pEnt, pcHCL, false, true);
    // If a hyperlink exists already, say so.
    if (pcHCL->count() != 0)
    {
    AcDbHyperlink * pcHO;
    acutPrintf("\nThe following hyperlink info already exists
    on this entity:");
    // Iterate through collection and print existing hyperlinks.
    int i = 0;
    for (i = 0; i < pcHCL->count(); i++)
    {
    // Get point to current hyperlink object.
    pcHO = pcHCL->item(i);
    acutPrintf("\nHyperlink name: %s", pcHO->name());
    acutPrintf("\nHyperlink location: %s",
    pcHO->subLocation());
    acutPrintf("\nHyperlink description: %s",
    pcHO->description());
    }
    acutPrintf("\n** All will be replaced.**");
    // Remove existing hyperlinks from collection.
    // RemoveAt will delete objects too.
    for (i = pcHCL->count() - 1; i >= 0; i--)
    {
    pcHCL->removeAt(i);
    }
    }
    // Get new hyperlinks for this entity.
    for (;;)
    {
    acutPrintf("\nEnter null name, location, and description to
    terminate input requests.");
    // Prompt user for name and description.
    char sName[100], sLocation[100], sDescription[100];
    if (acedGetString(TRUE, "\nEnter hyperlink name: ", sName) != RTNORM)
    acutPrintf("Invalid input\n");
    if (acedGetString(TRUE, "\nEnter hyperlink location: ", sLocation) != RTNORM)
    acutPrintf("Invalid input\n");
    if (acedGetString(TRUE, "\nEnter hyperlink description: ", sDescription) != RTNORM)
    acutPrintf("Invalid input\n");
    // Add hyperlink or exit prompting.
    if (strcmp(sName, "") || strcmp(sLocation, "") || strcmp(sDescription, ""))
    pcHCL->addTail(sName, sDescription, sLocation);
    else
    break;
    }
    // Add these hyperlinks to the selected entity (opened above).
    ACRX_X_CALL(pEnt, AcDbEntityHyperlinkPE)->
    setHyperlinkCollection(pEnt, pcHCL);
    // Delete the collection. The collection will delete all its
    // contained hyperlink objects.
    delete pcHCL;
    // Close the object.
    pEnt->close();
    }

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

    Следующий пример иллюстрирует, как использовать AcGi. Сначала, это сохраняет текущие значения свойства примитива на цвет, linetype, и уровень. Тогда это изменяет номер цвета черты под-примитива к синему и рисует ломаную линию с тремя точками. Затем, это изменяет номер цвета черты подпримитива к текущему цвету уровня, изменяет значение linetype к DASHDOT, и рисует xline.
    Типовой код включает две функции, getLinetypeFromString () и getLayerIdFromString (), которые позволяют Вам получать ID для linetype или уровня от строки.
    ОБРАТИТЕ ВНИМАНИЕ Практически, эти функции могли бы также не спешить, использование в пределах worldDraw (), и объектных ID должно быть сохранено и использоваться непосредственно.
    static Acad::ErrorStatus
    getLinetypeIdFromString(const char* str, AcDbObjectId& id);
    static Acad::ErrorStatus
    getLayerIdFromString(const char* str, AcDbObjectId& id);
    Adesk::Boolean
    AsdkTraitsSamp::worldDraw(AcGiWorldDraw* pW)
    {
    // At this point, the current property traits are
    // the entity’s property traits. If the current
    // property traits are changed and you want to
    // reapply the entity’s property traits, this is
    // the place to save them.
    //
    Adesk::UInt16 entity_color
    = pW->subEntityTraits().color();
    AcDbObjectId entity_linetype
    = pW->subEntityTraits().lineTypeId();
    AcDbObjectId entity_layer
    = pW->subEntityTraits().layerId();
    // Override the current color and make it blue.
    //
    pW->subEntityTraits().setColor(kBlue);
    // Draw a blue 3-point polyline.
    //
    int num_pts = 3;
    AcGePoint3d *pVerts = new AcGePoint3d[num_pts];
    pVerts[0] = AcGePoint3d(0.0, 0.0, 0);
    pVerts[1] = AcGePoint3d(1.0, 0.0, 0);
    pVerts[2] = AcGePoint3d(1.0, 1.0, 0);
    pW->geometry().polyline(num_pts, pVerts);
    // Force the current color to use current layer’s color.
    //
    pW->subEntityTraits().setColor(kColorByLayer);
    // Force current line type to DASHDOT. If
    // DASHDOT is not loaded, the current linetype
    // will still be in effect.
    //
    AcDbObjectId dashdotId;

    if (getLinetypeIdFromString("DASHDOT", dashdotId) == Acad::eOk)
    {
    pW->subEntityTraits().setLineType(dashdotId);
    }
    // Force current layer to "MY_LAYER". If
    // "MY_LAYER" is not loaded, the current layer
    // will still be in effect.
    //
    AcDbObjectId layerId;
    if (getLayerIdFromString("MY_LAYER", layerId) == Acad::eOk)
    {
    pW->subEntityTraits().setLayer(layerId);
    }
    // Draw a DASHDOT xline in "MY_LAYER"’s color.
    //
    pW->geometry().xline(pVerts[0], pVerts[2]);
    delete [] pVerts;
    return Adesk::kTrue;
    }
    // A useful function that gets the linetype ID from the
    // linetype’s name; the name must be in upper case.
    //
    static Acad::ErrorStatus
    getLinetypeIdFromString(const char* str, AcDbObjectId& id)
    {
    Acad::ErrorStatus err;
    // Get the table of currently loaded linetypes.
    //
    AcDbLinetypeTable *pLinetypeTable;
    err = acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pLinetypeTable, AcDb::kForRead);
    if (err != Acad::eOk)
    return err;
    // Get the ID of the linetype with the name that
    // str contains.
    //
    err = pLinetypeTable->getAt(str, id, Adesk::kTrue);
    pLinetypeTable->close();
    return err;
    }
    // A useful function that gets the layer ID from the
    // layer’s name; the layer name must be in upper case.
    //
    static Acad::ErrorStatus
    getLayerIdFromString(const char* str, AcDbObjectId& id)
    {
    Acad::ErrorStatus err;
    // Get the table of currently loaded layers.
    //
    AcDbLayerTable *pLayerTable;
    err = acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pLayerTable, AcDb::kForRead);
    if (err != Acad::eOk)
    return err;
    // Get the ID of the layer with the name that str
    // contains.
    //
    err = pLayerTable->getAt(str, id, Adesk::kTrue);
    pLayerTable->close();
    return err;
    }

    Пример MDI-ЗНАЮЩЕГО приложения

    Следующий пример показывает простое ObjectARX-приложение, которое MDI-ЗНАЕТ.
    Это - код примера от “ Использование Реактора Базы данных ” на странице 399, с кодом, добавленным, чтобы делать приложение MDI-Aware. Новый код показывается в жирном начертании.
    class AsdkDbReactor;
    class AsdkDocReactor: public AcApDocManagerReactor
    {
    public:
    virtual void documentToBeActivated(AcApDocument* pDoc);
    virtual void documentCreated(AcApDocument* pDoc);
    virtual void documentToBeDestroyed(AcApDocument* pDoc);
    };
    class AsdkPerDocData
    {
    friend class AsdkAppDocGlobals;
    public:
    AsdkPerDocData(AcApDocument* pDoc);
    private:
    AcApDocument* m_pDoc;
    AsdkPerDocData* m_pNext;
    long m_EntAcc; // Entity count
    AsdkDbReactor* m_pDbr;// Pointer to database reactor
    };

    class AsdkAppDocGlobals
    {
    public:
    AsdkAppDocGlobals(AcApDocument* pDoc);
    void setGlobals(AcApDocument* pDoc);
    void removeDocGlobals(AcApDocument *pDoc);
    void removeAllDocGlobals(AsdkPerDocData* pTarget);
    void unload();
    long &entityCount();
    void incrementEntityCount();
    void decrementEntityCount();
    AsdkDbReactor *dbReactor();
    void setDbReactor(AsdkDbReactor *pDb);
    private:
    AsdkPerDocData *m_pHead;
    AsdkPerDocData *m_pData;
    AsdkDocReactor *m_pDocReactor;
    };
    AsdkAppDocGlobals *gpAsdkAppDocGlobals;
    // 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);
    };
    // This is 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);
    gpAsdkAppDocGlobals->incrementEntityCount();

    acutPrintf("Entity Count = %d\n",
    gpAsdkAppDocGlobals->entityCount());
    }
    // This is 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);
    }
    // This is 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");
    gpAsdkAppDocGlobals->decrementEntityCount();
                    }
    else
    {
    printDbEvent(pObj, "object(Un)erased");
    gpAsdkAppDocGlobals->incrementEntityCount();
    }
    acutPrintf(" Db==%lx\n", (long) db);
    acutPrintf("Entity Count = %d\n",
    gpAsdkAppDocGlobals->entityCount());
    }
    // Prints the message passed in by pEvent; then
    // proceeds to call 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());
    }
    // Document swapping functions
    //
    void
    AsdkDocReactor::documentToBeActivated(AcApDocument *pDoc)
    {
    gpAsdkAppDocGlobals->setGlobals(pDoc);
    }
    void
    AsdkDocReactor::documentCreated(AcApDocument *pDoc)
    {
    gpAsdkAppDocGlobals->setGlobals(pDoc);


    }
    void
    AsdkDocReactor::documentToBeDestroyed(AcApDocument *pDoc)
    {
    gpAsdkAppDocGlobals->removeDocGlobals(pDoc);
    }
    AsdkPerDocData::AsdkPerDocData(AcApDocument *pDoc)
    {
    m_pDoc = pDoc;
    m_pNext = NULL;
    m_EntAcc = 0;
    m_pDbr = NULL;
    }
    AsdkAppDocGlobals::AsdkAppDocGlobals(AcApDocument *pDoc)
    {
    m_pData = m_pHead = NULL;
    m_pDocReactor = new AsdkDocReactor();
    acDocManager->addReactor(m_pDocReactor);
    }
    // Iterate through the list until the documents’s global data is
    // found. If it is not found, create a new set of document globals.
    //
    void
    AsdkAppDocGlobals::setGlobals(AcApDocument *pDoc)
    {
    AsdkPerDocData *p_data = m_pHead, *prev_data = m_pHead;
    while (p_data != NULL)
    {
    if (p_data->m_pDoc == pDoc)
    {
    m_pData = p_data;
    break;
    }
    prev_data = p_data;
    p_data = p_data->m_pNext;
    }
    if (p_data == NULL)
    {
    if (m_pHead == NULL)
    m_pHead = m_pData = new AsdkPerDocData(pDoc);
    else
    prev_data->m_pNext = m_pData = new AsdkPerDocData(pDoc);
    }
    }

    // Delete the globals associated with pDoc.
    //
    void
    AsdkAppDocGlobals::removeDocGlobals(AcApDocument *pDoc)
    {
    AsdkPerDocData *p_data = m_pHead, *prev_data = m_pHead;
    while (p_data != NULL)
    {
    if (p_data->m_pDoc == pDoc)
    {
    if (p_data == m_pHead)
    m_pHead = p_data->m_pNext;
    else
    prev_data->m_pNext = p_data->m_pNext;
    if (m_pData == p_data)
    m_pData = m_pHead;
    delete p_data;
    break;
    }
    prev_data = p_data;
    p_data = p_data->m_pNext;
    }
    }
    // Delete all the doc globals in the list (recursively).
    //
    void
    AsdkAppDocGlobals::removeAllDocGlobals(AsdkPerDocData *p_target)
    {
    if (p_target == NULL)
    return;
    if (p_target->m_pNext != NULL)
    removeAllDocGlobals(p_target->m_pNext);
    if (p_target->m_pDbr != NULL)
    {
    acdbHostApplicationServices()->
    workingDatabase()->removeReactor(p_target->m_pDbr);
    delete p_target->m_pDbr;
    p_target->m_pDbr = NULL;
    }
    delete p_target;
    }

    // Application was unloaded - delete everything associated with this


    // document.
    //
    void AsdkAppDocGlobals::unload()
    {
    acDocManager->removeReactor(m_pDocReactor);
    delete m_pDocReactor;
    removeAllDocGlobals(m_pHead);
    m_pHead = m_pData = NULL;
    }

    long &
    AsdkAppDocGlobals::entityCount()
    {
    return m_pData->m_EntAcc;
    }

    void
    AsdkAppDocGlobals::incrementEntityCount()
    {
    m_pData->m_EntAcc++;
    }

    void
    AsdkAppDocGlobals::decrementEntityCount()
    {
    m_pData->m_EntAcc--;
    }

    AsdkDbReactor *
    AsdkAppDocGlobals::dbReactor()
    {
    return m_pData->m_pDbr;
    }

    void
    AsdkAppDocGlobals::setDbReactor(AsdkDbReactor *pDb)
    {
    m_pData->m_pDbr = pDb;
    }
    // Adds a reactor to the database to monitor changes.
    // This can be called multiple times without any ill
    // effects because subsequent calls will be ignored.
    //
    void
    watchDb()
    {
    AsdkDbReactor *pDbr;
    if (gpAsdkAppDocGlobals->dbReactor() == NULL)
    {
    pDbr = new AsdkDbReactor();
    gpAsdkAppDocGlobals->setDbReactor(pDbr);
    acdbHostApplicationServices()->workingDatabase()->addReactor(pDbr);
    acutPrintf(
    " Added Database Reactor to "
    "acdbHostApplicationServices()->workingDatabase().\n");
    }
    }
    // Removes the database reactor.
    //
    void
    clearReactors()
    {
    AsdkDbReactor *pDbr;
    if ((pDbr = gpAsdkAppDocGlobals->dbReactor()) != NULL)
    {
    acdbHostApplicationServices()->workingDatabase()->removeReactor(pDbr);
    delete pDbr;
    gpAsdkAppDocGlobals->setDbReactor(NULL);
    }
    }
    // ObjectARX entry point function
    //
    AcRx::AppRetCode
    acrxEntryPoint(AcRx::AppMsgCode msg, void* appId)
    {
    switch (msg) {
    case AcRx::kInitAppMsg:
    acrxUnlockApplication(appId);
    acrxRegisterAppMDIAware(appId);
    gpAsdkAppDocGlobals = new AsdkAppDocGlobals(curDoc());
    gpAsdkAppDocGlobals->setGlobals(curDoc());
    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:
    if (gpAsdkAppDocGlobals != NULL)
    {
    gpAsdkAppDocGlobals->unload();
    delete gpAsdkAppDocGlobals;
    gpAsdkAppDocGlobals = NULL;
    }
    acedRegCmds->removeGroup("ASDK_NOTIFY_TEST");
    break;
    }
    return AcRx::kRetOK;
    }

    Пример Операций Базы данных

    Следующий пример показывает createDwg () подпрограмма, которая создает новую базу данных, получает образцовый пространственный блочный отчет{*запись*} таблицы, и создает два круга, которые добавлены, чтобы моделировать пространство{*пробел*}. Это использует AcDbDatabase:: saveAs () функция, чтобы сохранить{*экономить*} рисунок. Вторая подпрограмма, readDwg (), читает в сохраненном рисунке, открывает образцовый пространственный блочный отчет{*запись*} таблицы, и выполняет итерации через это, печать имена класса объектов, которые это содержит.
    void
    createDwg()
    {
    AcDbDatabase *pDb = new AcDbDatabase();
    AcDbBlockTable *pBtbl;
    pDb->getSymbolTable(pBtbl, AcDb::kForRead);
    AcDbBlockTableRecord *pBtblRcd;
    pBtbl->getAt(ACDB_MODEL_SPACE, pBtblRcd,
    AcDb::kForWrite);
    pBtbl->close();
    AcDbCircle *pCir1 = new AcDbCircle(AcGePoint3d(1,1,1),
    AcGeVector3d(0,0,1),
    1.0),
    *pCir2 = new AcDbCircle(AcGePoint3d(4,4,4),
    AcGeVector3d(0,0,1),
    2.0);
    pBtblRcd->appendAcDbEntity(pCir1);
    pCir1->close();
    pBtblRcd->appendAcDbEntity(pCir2);
    pCir2->close();
    pBtblRcd->close();
    // AcDbDatabase::saveAs() does not automatically
    // append a DWG file extension, so it
    // must be specified.
    //
    pDb->saveAs("test1.dwg");
    delete pDb;
    }
    void
    readDwg()
    {
    // Set constructor parameter to kFalse so that the
    // database will be constructed empty. This way only
    // what is read in will be in the database.
    //
    AcDbDatabase *pDb = new AcDbDatabase(Adesk::kFalse);
    // The AcDbDatabase::readDwgFile() function
    // automatically appends a DWG extension if it is not
    // specified in the filename parameter.
    //
    pDb->readDwgFile("test1.dwg");
    // Open the model space block table record.
    //
    AcDbBlockTable *pBlkTbl;
    pDb->getSymbolTable(pBlkTbl, AcDb::kForRead);
    AcDbBlockTableRecord *pBlkTblRcd;
    pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd,
    AcDb::kForRead);
    pBlkTbl->close();
    AcDbBlockTableRecordIterator *pBlkTblRcdItr;
    pBlkTblRcd->newIterator(pBlkTblRcdItr);
    AcDbEntity *pEnt;
    for (pBlkTblRcdItr->start(); !pBlkTblRcdItr->done(); pBlkTblRcdItr->step())
    {
    pBlkTblRcdItr->getEntity(pEnt,
    AcDb::kForRead);
    acutPrintf("classname: %s\n",
    (pEnt->isA())->name());
    pEnt->close();
    }
    pBlkTblRcd->close();
    delete pBlkTblRcdItr;
    delete pDb;
    }

    Пример отсечения границ

    В следующем примере, граница обрезки помещена на стек границы обрезки прежде, чем что - нибудь рисует и вытолкнуто от снова, как только рисунок в этот объект полон:
    Adesk::Boolean
    MyObject::worldDraw(AcGiWorldDraw* pDraw)
    {
    AcGiWorldGeometry * pGeom = &pDraw->geometry();
    pGeom->pushModelTransform(myTransform());
    AcGiClipBoundary cb;
    cb.m_bDrawBoundary= true;
    cb.m_vNormal = AcGeVector3d::kZAxis;
    cb.m_ptPoint = AcGePoint3d::kOrigin;
    // Two points treated as a rectangle, three creates a triangle
    cb.m_aptPoints.append(AcGePoint2d(0,0));
    cb.m_aptPoints.append(AcGePoint2d(5,5));
    // We are clipping in our own space
    cb.m_xToClipSpace.setToIdentity();
    cb.m_xInverseBlockRefXForm = myTransform().inverse();
    // No Z clipping
    cb.m_bClippingBack = cb.m_bClippingFront = false;
    cb.m_dFrontClipZ = cb.m_dBackClipZ = 0.;
    Adesk::Boolean bPopClipBoundary = pGeom->pushClipBoundary(&cb);
    // Draw something
    pGeom->circle(...);
    pGeom->popModelTransform();
    if(bPopClipBoundary){ pGeom->popClipBoundary(); }
    return true; // world-only
    }
    Так как это отсечение - комплексная операция, некоторые AcGi
    выполнение не могли бы поддерживать это полностью. В этом случае, AcGi выполнение может возвращать ложь от pushClipBoundary (), и Вы не должны вызвать popClipBoundary ().

    Пример расширения протокола

    Этот пример расширения протокола разделен на три части:
    §
    Объявление и определение четырех классов расширения протокола: AsdkEntTemperature, AsdkDefaultTemperature, AsdkRegionTemperature и AsdkCircleTemperature.
    § выполнение energy() для команды ENERGY, которая позволяет пользователю выбирать примитив и затем, вычисляет температуру для того примитива.
    § ObjectARX модуль связывают с помощью интерфейса функции: initApp (), unloadApp () и acrxEntryPoint ().
    // This is the AsdkEntTemperature protocol extension abstract base
    // class. Notice that this is the lowest level that uses
    // the ACRX macros.
    //
    class AsdkEntTemperature : public AcRxObject
    {
    public:
    ACRX_DECLARE_MEMBERS(AsdkEntTemperature);
    virtual double reflectedEnergy(AcDbEntity*) const = 0;
    };
    ACRX_NO_CONS_DEFINE_MEMBERS(AsdkEntTemperature, AcRxObject);
    // This is the default implementation to be attached to AcDbEntity
    // as a catch-all. This guarantees that this protocol extension will
    // be found for any entity, so the search up the AcRxClass tree will
    // not fail and abort AutoCAD.
    //
    class AsdkDefaultTemperature : public AsdkEntTemperature
    {
    public:
    virtual double reflectedEnergy(AcDbEntity* pEnt) const;
    };
    double
    AsdkDefaultTemperature::reflectedEnergy( AcDbEntity* pEnt) const
    {
    acutPrintf( "\nThis entity has no area, and no reflection.\n");
    return -1.0;
    }
    // AsdkEntTemperature implementation for Regions
    //
    class AsdkRegionTemperature : public AsdkEntTemperature
    {
    public:
    virtual double reflectedEnergy(AcDbEntity* pEnt) const;
    };
    double
    AsdkRegionTemperature::reflectedEnergy( AcDbEntity* pEnt) const
    {
    AcDbRegion *pRegion = AcDbRegion::cast(pEnt);
    if (pRegion == NULL)
    acutPrintf("\nThe impossible has happened!");
    // Compute the reflected energy as the region area multiplied
    // by a dummy constant.
    //
    double retVal;

    if (pRegion->getArea(retVal) != Acad::eOk)
    return -1.0;
    return retVal * 42.0;
    }
    // AsdkEntTemperature implementation for circles
    //
    class AsdkCircleTemperature : public AsdkEntTemperature
    {
    public:
    virtual double reflectedEnergy(AcDbEntity* pEnt) const;
    };
    double
    AsdkCircleTemperature::reflectedEnergy( AcDbEntity* pEnt) const
    {
    AcDbCircle *pCircle = AcDbCircle::cast(pEnt);
    // Compute the reflected energy in a manner distinctly
    // different than for AcDbRegion.
    //
    return pCircle->radius() * 6.21 * 42.0;
    }
    // This function has the user select an entity and then
    // calls the reflectedEnergy() function in the protocol
    // extension class attached to that entity’s class.
    //
    void
    energy()
    {
    AcDbEntity *pEnt;
    AcDbObjectId pEntId;
    ads_name en;
    ads_point pt;
    if (acedEntSel("\nSelect an Entity: ", en, pt) != RTNORM)
    {
    acutPrintf("Nothing Selected\n");
    return;
    }
    acdbGetObjectId(pEntId, en);
    acdbOpenObject(pEnt, pEntId, AcDb::kForRead);
    // call the protocol extension class’s method
    //
    double eTemp = ACRX_X_CALL(pEnt, AsdkEntTemperature)->reflectedEnergy(pEnt);
    acutPrintf("\nEnergy == %f\n", eTemp);
    pEnt->close();
    }
    // Pointers for protocol extension objects. These pointers
    // are global so that they can be accessed during
    // initialization and cleanup.
    //
    AsdkDefaultTemperature *pDefaultTemp;
    AsdkRegionTemperature *pRegionTemp;
    AsdkCircleTemperature *pCircleTemp;
    // Initialization function called from acrxEntryPoint() during
    // kInitAppMsg case. This function is used to add commands
    // to the command stack and to add protocol extension
    // objects to classes.
    //
    void
    initApp()
    {
    acrxRegisterService("AsdkTemperature");
    AsdkEntTemperature::rxInit();
    acrxBuildClassHierarchy();
    pDefaultTemp = new AsdkDefaultTemperature();
    pRegionTemp = new AsdkRegionTemperature();
    pCircleTemp = new AsdkCircleTemperature();
    // Add the protocol extension objects to the appropriate


    // AcRxClass objects.
    //
    AcDbEntity::desc()->addX(AsdkEntTemperature::desc(), pDefaultTemp);
    AcDbRegion::desc()->addX(AsdkEntTemperature::desc(), pRegionTemp);
    AcDbCircle::desc()->addX(AsdkEntTemperature::desc(), pCircleTemp);
    acedRegCmds->addCommand("ASDK_TEMPERATURE_APP",
    "ASDK_ENERGY", "ENERGY", ACRX_CMD_TRANSPARENT,
    energy);
    }
    void
    unloadApp()
    {
    delete acrxServiceDictionary->remove("AsdkTemperature");
    acedRegCmds->removeGroup("ASDK_TEMPERATURE_APP");
    // Remove protocol extension objects from the AcRxClass
    // object tree. This must be done before removing the
    // AsdkEntTemperature class from the ACRX runtime class
    // hierarchy, so the AsdkEntTemperature::desc()
    // still exists.
    //
    AcDbEntity::desc()->delX(AsdkEntTemperature::desc());
    delete pDefaultTemp;
    AcDbRegion::desc()->delX(AsdkEntTemperature::desc());
    delete pRegionTemp;
    AcDbCircle::desc()->delX(AsdkEntTemperature::desc());
    delete pCircleTemp;
    // Remove the AsdkEntTemperature class from the ARX
    // runtime class hierarchy.
    //
    deleteAcRxClass(AsdkEntTemperature::desc());
    }
    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();
    }
    return AcRx::kRetOK;
    }

    Пример вложенных транзакций

    Следующий пример включает три вложенных транзакции. Последовательность событий следует.
    Создавать вложенные транзакции
    1 Создают многоугольник и переносят это к базе данных.
    2 Транзакция Начала 1:
  • Выбирают многоугольник и получают указатель на это. Откройте это для чтения.

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

  • Создают цилиндр в середине расширенного{*продленного*} многоугольника.

  • 3 Транзакция Начала 2: Вычтите цилиндр от вытеснения (создает отверстие в середине твердых).
    4 Транзакция Начала 3:
  • Сектор форма в половине по X/Z плану и перемещению это по X оси, так что Вы можете рассматривать эти две части.

  • Прерывают транзакцию? Ответ да.

  • 5 Транзакции Начала 3 (снова): Сектор форма в половине по Y/Z плану и перемещению это по Y.
    6 Конечных Транзакции 3.
    7 Конечных Транзакции 2.
    ОБРАТИТЕ ВНИМАНИЕ, прерываетесь ли Вы в этой точке, транзакции 2 и 3 оба отменены. Если Вы прерываете содержащую транзакцию, все вложенные транзакции прерваны, даже если они были успешно закончены.
    8 Конечных Транзакции 1.
    Следующее - код для этого примера:
    void
    transactCommand()
    {
    Adesk::Boolean interrupted;
    Acad::ErrorStatus es = Acad::eOk;
    AcDbObjectId savedCylinderId,savedExtrusionId;
    // Create a poly and post it to the database.
    //
    acutPrintf("\nCreating a poly...Please supply the"
    " required input.");
    if ((es = createAndPostPoly()) != Acad::eOk)
    return;
    // Start a transaction.
    //
    AcTransaction *pTrans = actrTransactionManager->startTransaction();
    assert(pTrans != NULL);
    acutPrintf("\n\n###### Started transaction one." " ######\n");
    // Select the poly and extrude it.
    //
    AcDbObject *pObj = NULL;
    AsdkPoly *pPoly = NULL;
    AcDb3dSolid *pSolid = NULL;
    AcDbObjectId objId;
    ads_name ename;
    ads_point pickpt;
    for (;;) {
    switch (acedEntSel("\nSelect a polygon: ", ename, pickpt))
    {
    case RTNORM:
    acdbGetObjectId(objId, ename);
    if ((es = pTrans->getObject(pObj, objId, AcDb::kForRead)) != Acad::eOk)

    {
    acutPrintf("\nFailed to obtain an object"
    " through transaction.");
    actrTransactionManager->abortTransaction();
    return;
    }
    assert(pObj != NULL);
    pPoly = AsdkPoly::cast(pObj);
    if (pPoly == NULL) {
    acutPrintf("\nNot a polygon. Try again");
    continue;
    }
    break;
    case RTNONE:
    case RTCAN:
    actrTransactionManager->abortTransaction();
    return;
    default:
    continue;
    }
    break;
    }
    // Now that a poly is created, convert it to a region
    // and extrude it.
    //
    acutPrintf("\nWe will be extruding the poly.");
    AcGePoint2d c2d = pPoly->center();
    ads_point pt;
    pt[0] = c2d[0]; pt[1] = c2d[1]; pt[2] = pPoly->elevation();
    acdbEcs2Ucs(pt,pt,asDblArray(pPoly->normal()),Adesk::kFalse);
    double height;
    if (acedGetDist(pt, "\nEnter Extrusion height: ", &height) != RTNORM)
    {
    actrTransactionManager->abortTransaction();
    return;
    }
    if ((es = extrudePoly(pPoly, height,savedExtrusionId)) != Acad::eOk) {
    actrTransactionManager->abortTransaction();
    return;
    }
    // Create a cylinder at the center of the polygon of
    // the same height as the extruded poly.
    //
    double radius = (pPoly->startPoint() - pPoly->center()).length() * 0.5;
    pSolid = new AcDb3dSolid;
    assert(pSolid != NULL);
    pSolid->createFrustum(height, radius, radius, radius);
    AcGeMatrix3d mat(AcGeMatrix3d::translation(
    pPoly->elevation()*pPoly->normal())*
    AcGeMatrix3d::planeToWorld(pPoly->normal()));
    pSolid->transformBy(mat);
    // Move it up again by half the height along
    // the normal.
    //
    AcGeVector3d x(1, 0, 0), y(0, 1, 0), z(0, 0, 1);
    AcGePoint3d moveBy(pPoly->normal()[0] * height * 0.5,
    pPoly->normal()[1] * height * 0.5,
    pPoly->normal()[2] * height * 0.5);
    mat.setCoordSystem(moveBy, x, y, z);
    pSolid->transformBy(mat);
    addToDb(pSolid, savedCylinderId);
    actrTransactionManager->addNewlyCreatedDBRObject(pSolid);
    pSolid->draw();
    acutPrintf("\nCreated a cylinder at the center of"


    " the poly.");
    // Start another transaction. Ask the user to select
    // the extruded solid followed by selecting the
    // cylinder. Make a hole in the extruded solid by
    // subtracting the cylinder from it.
    //
    pTrans = actrTransactionManager->startTransaction();
    assert(pTrans != NULL);
    acutPrintf("\n\n###### Started transaction two." " ######\n");
    AcDb3dSolid *pExtrusion, *pCylinder;
    if ((es = getASolid("\nSelect the extrusion: ", pTrans,
    AcDb::kForWrite, savedExtrusionId, pExtrusion))
    != Acad::eOk)
    {
    actrTransactionManager->abortTransaction();
    actrTransactionManager->abortTransaction();
    return;
    }
    assert(pExtrusion != NULL);
    if ((es = getASolid("\nSelect the cylinder: ", pTrans,
    AcDb::kForWrite, savedCylinderId, pCylinder))
    != Acad::eOk)
    {
    actrTransactionManager->abortTransaction();
    actrTransactionManager->abortTransaction();
    return;
    }
    assert(pCylinder != NULL);
    pExtrusion->booleanOper(AcDb::kBoolSubtract, pCylinder);
    pExtrusion->draw();
    acutPrintf("\nSubtracted the cylinder from the"
    " extrusion.");
    // At this point, the cylinder is a NULL solid. Erase it.
    //
    assert(pCylinder->isNull());
    pCylinder->erase();
    // Start another transaction and slice the resulting
    // solid into two halves.
    //
    pTrans = actrTransactionManager->startTransaction();
    assert(pTrans != NULL);
    acutPrintf("\n\n##### Started transaction three."
    " ######\n");
    AcGeVector3d vec, normal;
    AcGePoint3d sp,center;
    pPoly->getStartPoint(sp);
    pPoly->getCenter(center);
    vec = sp - center;
    normal = pPoly->normal().crossProduct(vec);
    normal.normalize();
    AcGePlane sectionPlane(center, normal);
    AcDb3dSolid *pOtherHalf = NULL;
    pExtrusion->getSlice(sectionPlane, Adesk::kTrue,
    pOtherHalf);
    assert(pOtherHalf != NULL);
    // Move the other half three times the vector length
    // along the vector.
    //
    moveBy.set(vec[0] * 3.0, vec[1] * 3.0, vec[2] * 3.0);


    mat.setCoordSystem(moveBy, x, y, z);
    pOtherHalf->transformBy(mat);
    AcDbObjectId otherHalfId;
    addToDb(pOtherHalf, otherHalfId);
    actrTransactionManager->addNewlyCreatedDBRObject(pOtherHalf);
    pOtherHalf->draw();
    pExtrusion->draw();
    acutPrintf("\ nSliced the resulting solid into half"
    " and moved one piece.");
    // Now abort transaction three, to return to the hole in
    // the extrusion.
    //
    Adesk::Boolean yes = Adesk::kTrue;
    if (getYOrN("\nLet’s abort transaction three, yes?"
    " [Y] : ", Adesk::kTrue, yes,interrupted) == Acad::eOk
    && yes == Adesk::kTrue)
    {
    acutPrintf("\n\n$$$$$$ Aborting transaction"
    " three. $$$$$$\n");
    actrTransactionManager->abortTransaction();
    acutPrintf("\nBack to the un-sliced solid.");
    pExtrusion->draw();
    char option[256];
    acedGetKword("\nHit any key to continue.", option);
    } else {
    acutPrintf("\n\n>>>>>> Ending transaction three."
    " <<<<<<\n");
    actrTransactionManager->endTransaction();
    }
    // Start another transaction (three again). This time,
    // slice the solid along a plane that is perpendicular
    // to the plane we used last time: that is the slice
    // we really wanted.
    //
    pTrans = actrTransactionManager->startTransaction();
    assert(pTrans != NULL);
    acutPrintf("\n\n##### Started transaction three."
    " ######\n");
    moveBy.set(normal[0] * 3.0, normal[1] * 3.0,
    normal[2] * 3.0);
    normal = vec;
    normal.normalize();
    sectionPlane.set(center, normal);
    pOtherHalf = NULL;
    pExtrusion->getSlice(sectionPlane, Adesk::kTrue,
    pOtherHalf);
    assert(pOtherHalf != NULL);
    mat.setCoordSystem(moveBy, x, y, z);
    pOtherHalf->transformBy(mat);
    addToDb(pOtherHalf, otherHalfId);
    actrTransactionManager
    ->addNewlyCreatedDBRObject(pOtherHalf);
    pOtherHalf->draw();
    pExtrusion->draw();
    acutPrintf("\nSliced the resulting solid into half"


    " along a plane");
    acutPrintf("\ nperpendicular to the old one and moved"
    " one piece.");
    // Now, give the user the option to end all the transactions.
    //
    yes = Adesk::kFalse;
    if (getYOrN("\nAbort transaction three? : ",
    Adesk::kFalse, yes,interrupted) == Acad::eOk
    && yes == Adesk::kTrue)
    {
    acutPrintf("\n\n$$$$$$ Aborting transaction"
    " three. $$$$$$\n");
    actrTransactionManager->abortTransaction();
    acutPrintf("\nBack to the un-sliced solid.");
    } else {
    acutPrintf("\n\n>>>>>> Ending transaction three."
    " <<<<<<\n");
    actrTransactionManager->endTransaction();
    }
    yes = Adesk::kFalse;
    if (getYOrN("\nAbort transaction two? : ",
    Adesk::kFalse, yes,interrupted) == Acad::eOk
    && yes == Adesk::kTrue)
    {
    acutPrintf("\n\n$$$$$$ Aborting transaction two."
    " $$$$$$\n");
    actrTransactionManager->abortTransaction();
    acutPrintf("\nBack to separate extrusion and"
    " cylinder.");
    } else {
    acutPrintf("\n\n>>>>>> Ending transaction two."
    " <<<<<<\n");
    actrTransactionManager->endTransaction();
    }
    yes = Adesk::kFalse;
    if (getYOrN("\nAbort transaction one? : ",
    Adesk::kFalse, yes,interrupted) == Acad::eOk
    && yes == Adesk::kTrue)
    {
    acutPrintf("\n\n$$$$$$ Aborting transaction one."
    " $$$$$$\n");
    actrTransactionManager->abortTransaction();
    acutPrintf("\nBack to just the Poly.");
    } else {
    actrTransactionManager->endTransaction();
    acutPrintf("\n\n>>>>>> Ending transaction one."
    " <<<<<<\n");
    }
    }
    static Acad::ErrorStatus
    createAndPostPoly()
    {
    int nSides = 0;
    while (nSides < 3) {
    acedInitGet(INP_NNEG, "");
    switch (acedGetInt("\nEnter number of sides: ", &nSides))


    {
    case RTNORM:
    if (nSides < 3)
    acutPrintf("\nNeed at least 3 sides.");
    break;
    default:
    return Acad::eInvalidInput;
    }
    }
    ads_point center, startPt, normal;
    if (acedGetPoint(NULL, "\nLocate center of polygon: ", center) != RTNORM)
    {
    return Acad::eInvalidInput;
    }
    startPt[0] = center[0];
    startPt[1] = center[1];
    startPt[2] = center[2];
    while (asPnt3d(startPt) == asPnt3d(center)) {
    switch (acedGetPoint(center, "\ nLocate start point of polygon: ", startPt)) {
    case RTNORM:
    if (asPnt3d(center) == asPnt3d(startPt))
    acutPrintf("\nPick a point different"
    " from the center.");
    break;
    default:
    return Acad::eInvalidInput;
    }
    }
    // Set the normal to the plane of the polygon to be
    // the same as the Z direction of the current UCS,
    // (0, 0, 1) since we also got the center and
    // start point in the current UCS. (acedGetPoint()
    // returns in the current UCS.)
    normal[X] = 0.0;
    normal[Y] = 0.0;
    normal[Z] = 1.0;
    acdbUcs2Wcs(normal, normal, Adesk::kTrue);
    acdbUcs2Ecs(center, center, normal, Adesk::kFalse);
    acdbUcs2Ecs(startPt, startPt, normal, Adesk::kFalse);
    double elev = center[2];
    AcGePoint2d cen = asPnt2d(center),
    start = asPnt2d(startPt);
    AcGeVector3d norm = asVec3d(normal);
    AsdkPoly *pPoly = new AsdkPoly;
    if (pPoly==NULL)
    return Acad::eOutOfMemory;
    Acad::ErrorStatus es;
    if ((es=pPoly->set(cen, start, nSides, norm, "transactPoly",elev))!=Acad::eOk)
    return es;
    pPoly->setDatabaseDefaults( acdbHostApplicationServices()->workingDatabase());
    postToDb(pPoly);
    return Acad::eOk;
    }
    // Extrudes the poly to a given height.
    //
    static Acad::ErrorStatus
    extrudePoly(AsdkPoly* pPoly, double height, AcDbObjectId& savedExtrusionId)
    {
    Acad::ErrorStatus es = Acad::eOk;
    // Explode to a set of lines.
    //
    AcDbVoidPtrArray lines;
    pPoly->explode(lines);
    // Create a region from the set of lines.
    //
    AcDbVoidPtrArray regions;
    AcDbRegion::createFromCurves(lines, regions);


    assert(regions.length() == 1);
    AcDbRegion *pRegion
    = AcDbRegion::cast((AcRxObject*)regions[0]);
    assert(pRegion != NULL);
    // Extrude the region to create a solid.
    //
    AcDb3dSolid *pSolid = new AcDb3dSolid;
    assert(pSolid != NULL);
    pSolid->extrude(pRegion, height, 0.0);
    for (int i = 0; i < lines.length(); i++) {
    delete (AcRxObject*)lines[i];
    }
    for (i = 0; i < regions.length(); i++) {
    delete (AcRxObject*)regions[i];
    }
    // Now we have a solid. Add it to database, then
    // associate the solid with a transaction. After
    // this, transaction management is in charge of
    // maintaining it.
    //
    pSolid->setPropertiesFrom(pPoly);
    addToDb(pSolid, savedExtrusionId);
    actrTransactionManager->addNewlyCreatedDBRObject(pSolid);
    pSolid->draw();
    return Acad::eOk;
    }
    static Acad::ErrorStatus
    getASolid(char* prompt,
    AcTransaction* pTransaction,
    AcDb::OpenMode mode,
    AcDbObjectId checkWithThisId,
    AcDb3dSolid*& pSolid)
    {
    AcDbObject *pObj = NULL;
    AcDbObjectId objId;
    ads_name ename;
    ads_point pickpt;
    for (;;) {
    switch (acedEntSel(prompt, ename, pickpt)) {
    case RTNORM:
    AOK(acdbGetObjectId(objId, ename));
    if (objId != checkWithThisId) {
    acutPrintf("\n Select the proper"
    " solid.");
    continue;
    }
    AOK(pTransaction->getObject(pObj, objId, mode));
    assert(pObj != NULL);
    pSolid = AcDb3dSolid::cast(pObj);
    if (pSolid == NULL) {
    acutPrintf("\nNot a solid. Try again");
    AOK(pObj->close());
    continue;
    }
    break;
    case RTNONE:
    case RTCAN:
    return Acad::eInvalidInput;
    default:
    continue;
    }
    break;
    }
    return Acad::eOk;
    }

    Пример высвечивание

    Пример кода позже в этом разделе показывает, как высветить подпримитив.
    Следующая процедура перечисляет основные шаги.
    1 Получают GS маркер для выбранного примитива от набора выборов.
    2 Передают GS маркер к классу примитива, который будет преобразован{*конвертирован*} к пути подпримитива, используя getSubentPathsAtGsMarker () функция. Определите тип подпримитива, вы заинтересованы (вершина, край, лицо).
    3, как только Вы имеете путь к выбранному подпримитиву, вы готовы назвать подсветку () функцией, проходящей в правильном пути подпримитива.

    Выбор Примитива
    Для выбора, вы будете использовать комбинацию глобальных функций. Сначала, используйте acedSSGet () функция, чтобы получить набор выборов. Тогда, используйте acedSSNameX () функция, чтобы получить подпримитив GS маркер для выбранного примитива.
    int acedSSGet(
    const char *str,
    const void *pt1,
    const ads_point pt2,
    const struct resbuf *entmask,
    ads_name ss);
    int acedSSNameX(
    struct resbuf** rbpp,
    const ads_name ss,
    const longvi);

    Преобразование GS Маркеры к Путям Подпримитива
    Используйте getSubentPathsAtGsMarker () функция, чтобы получить подпримитив для GS маркера, возвращенного acedSSNameX () функция. Законченный синтаксис для этой функции
    virtual Acad::ErrorStatus
    AcDbEntity::getSubentPathsAtGsMarker(
    AcDb::SubentType type,
    int gsMark,
    const AcGePoint3d& pickPoint,
    const AcGeMatrix3d& viewXform,
    int& numPaths,
    AcDbFullSubentPath*& subentPaths
    int numInserts = 0,
    AcDbObjectId* entAndInsertStack = NULL) const;
    Первый параметр к этой функции - тип подпримитива, вы заинтересованы (вершина, край, или лицо). В примере закодируют в “ Высвечивание{*увеличение яркости*} - tity, ” первый запрос к этой функции определяет kEdgeSubentType, потому что вы собираетесь высвечивать соответствующий край. Второй запрос к getSubentPathsAtGsMarker () функция определяет kFaceSubentType, потому что вы собираетесь высвечивать каждое лицо, связанное с выбранным подпримитивом.

    PickPoint и viewXform параметры используются как дополнительный ввод для некоторых примитивов (типа mlines) когда GS маркер один не обеспечивает достаточно информации, чтобы возвратить пути подпримитива. В примере закодируют в “ Высвечивание{*увеличение яркости*} Подпримитива, ” они не используются.
    NumInserts и entAndInsertStack параметры используются для вложенных вставок. И acedNEntSel () и acedNEntSelP () функции возвращают название{*имя*} примитива уровня листа, плюс стек вставок.
    Высвечивание{*увеличение яркости*} Подпримитива
    Как только вы получили путь подпримитива к выбранному примитиву, самая твердая{*самая трудная*} часть этого процесса закончена. Теперь, Вы нуждаетесь только в запросе подсветка () функция и проход в пути подпримитива. Если Вы вызываете{*называете*} подсветку () функция без любых параметров, значение по умолчанию должна высветить целый примитив.
    Следующий типовой код иллюстрирует шаги, описанные для выбора примитива, получение пути подпримитива, и высвечивания{*увеличения яркости*} различных типов подпримитивов, связанных с GS
    маркером. Этот код также иллюстрирует другую полезную функцию подпримитива:
    virtual AcDbEntity*
    AcDbEntity::subentPtr(const AcDbFullSubentPath& id) const;
    Эта функция возвращает указатель на копию подпримитива, описанного указанным путем, который может тогда быть добавлен к базе данных (как показано в примере).
    ПРИМЕЧАНИЕ ожидается, что Вы будете должны перегрузить функции getSubentPathsAtGsMarker (), getGsMarkersAtSubentPath () и subentPtr () когда, Вы создает новые подклассы AcDbEntity. Подсветка () функция, однако, осуществлена в AcDbEntity, выравнивают, и как ожидается,  будет перегружен. Однако, если это перегружено, любое новое выполнение этой функции должно назвать AcDbEntity:: подсветкой () чтобы исполнить высвечивание{*увеличение яркости*}.
    // Эта функция вызывает{*называет*} getObjectAndGsMarker ()
    //  чтобы получить объект ID твердых и его gsmarker. Это тогда вызывает


    //  highlightEdge (), highlightFaces (), и highlightAll () чтобы высветить выбранный
    //  край, все лица, окружающие тот край, и затем твердое целое.
    //
    void
    highlightTest()
    {
    AcDbObjectId objId;
    int marker;
    if (getObjectAndGsMarker(objId, marker) != Acad::eOk)
    return;
    highlightEdge(objId, marker);
    highlightFaces(objId, marker);
    highlightAll(objId);
    }
    // This function uses acedSSGet() to let the user select a
    // single entity. It then passes this selection set to
    // acedSSNameX() to get the gsmarker. Finally, the entity name
    // in the selection set is used to obtain the object ID of
    // the selected entity.
    //
    Acad::ErrorStatus
    getObjectAndGsMarker(AcDbObjectId& objId, int& marker)
    {
    ads_name sset;
    if (acedSSGet("_:S", NULL, NULL, NULL, sset) != RTNORM) {
    acutPrintf("\nacedSSGet has failed");
    return Acad::eInvalidAdsName;
    }
    // Get the entity from the selection set and its
    // subentity ID. This code assumes that the user
    // selected only one item, a solid.
    //
    struct resbuf *pRb;
    if (acedSSNameX(&pRb, sset, 0) != RTNORM) {
    acedSSFree(sset);
    return Acad::eAmbiguousOutput;
    }
    acedSSFree(sset);
    // Walk the list to the third item, which is the selected
    // entity’s entity name.
    //
    struct resbuf *pTemp;
    int i;
    for (i=1, pTemp = pRb;i<3;i++, pTemp = pTemp->rbnext)
    { ; }
    ads_name ename;
    ads_name_set(pTemp->resval.rlname, ename);
    // Move on to the fourth list element, which is the gsmarker.
    //
    pTemp = pTemp->rbnext;
    marker = pTemp->resval.rint;
    acutRelRb(pRb);
    acdbGetObjectId(objId, ename);
    return Acad::eOk;
    }
    // This function accepts an object ID and a gsmarker.
    // The object is opened, the gsmarker is used to get the
    // AcDbFullSubentIdPath, which is then used to highlight
    // and unhighlight the edge used to select the object.
    // Next, the object’s subentPtr() function is used to get
    // a copy of the edge. This copy is then added to the
    // database. Finally, the object is closed.


    //
    void
    highlightEdge(const AcDbObjectId& objId, const int marker)
    {
    char dummy[133]; // space for acedGetString pauses below
    AcDbEntity *pEnt;
    acdbOpenAcDbEntity(pEnt, objId, AcDb::kForRead);
    // Get the subentity ID for the edge that is picked
    //
    AcGePoint3d pickpnt;
    AcGeMatrix3d xform;
    int numIds;
    AcDbFullSubentPath *subentIds;
    pEnt->getSubentPathsAtGsMarker(AcDb::kEdgeSubentType,
    marker, pickpnt, xform, numIds, subentIds);
    // At this point the subentId’s variable contains the
    // address of an array of AcDbFullSubentPath objects.
    // The array should be one element long, so the picked
    // edge’s AcDbFullSubentPath is in subentIds[0].
    //
    // For objects with no edges (such as a sphere), the
    // code to highlight an edge is meaningless and must
    // be skipped.
    //
    if (numIds > 0) {
    // Highlight the edge.
    //
    pEnt->highlight(subentIds[0]);
    // Pause to let user see the effect.
    //
    acedGetString(0, "\npress to continue...",
    dummy);
    // Unhighlight the picked edge.
    //
    pEnt->unhighlight(subentIds[0]);
    // Get a copy of the edge, and add it to the database.
    //
    AcDbEntity *pEntCpy = pEnt->subentPtr(subentIds[0]);
    AcDbObjectId objId;
    addToModelSpace(objId, pEntCpy);
    }
    delete []subentIds;
    pEnt->close();
    }
    // This function accepts an object ID and a gsmarker.
    // The object is opened, the gsmarker is used to get the
    // AcDbFullSubentIdPath, which is then used to highlight
    // and unhighlight faces that share the edge used to
    // select the object. The object is then closed.
    //
    void
    highlightFaces(const AcDbObjectId& objId, const int marker)
    {
    char dummy[133];
    AcDbEntity *pEnt;
    acdbOpenAcDbEntity(pEnt, objId, AcDb::kForRead);
    // Get the subentIds for the faces.
    //
    AcGePoint3d pickpnt;
    AcGeMatrix3d xform;
    int numIds;
    AcDbFullSubentPath *subentIds;
    pEnt->getSubentPathsAtGsMarker(AcDb::kFaceSubentType,
    marker, pickpnt, xform, numIds, subentIds);
    // Walk the subentIds list, highlighting each face subentity.


    //
    for (int i = 0;i < numIds; i++) {
    pEnt->highlight(subentIds[i]); // Highlight face.
    // Pause to let the user see the effect.
    //
    acedGetString(0, "\npress to continue...",
    dummy);
    pEnt->unhighlight(subentIds[i]);
    }
    delete []subentIds;
    pEnt->close();
    }
    // This function accepts an object ID. The object is opened,
    // and its highlight() and unhighlight() functions are
    // used with no parameters, to highlight and
    // unhighlight the edge used to select the object. The
    // object is then closed.
    //
    void
    highlightAll(const AcDbObjectId& objId)
    {
    char dummy[133];
    AcDbEntity *pEnt;
    acdbOpenAcDbEntity(pEnt, objId, AcDb::kForRead);
    // Highlight the whole solid.
    //
    pEnt->highlight();
    // Pause to let user see the effect.
    //
    acedGetString(0, "\npress to continue...",
    dummy);
    pEnt->unhighlight();
    pEnt->close();
    }
    Acad::ErrorStatus
    addToModelSpace(AcDbObjectId &objId, AcDbEntity* pEntity)
    {
    AcDbBlockTable *pBlockTable;
    AcDbBlockTableRecord *pSpaceRecord;
    acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pBlockTable, AcDb::kForRead);
    pBlockTable->getAt(ACDB_MODEL_SPACE, pSpaceRecord,
    AcDb::kForWrite);
    pSpaceRecord->appendAcDbEntity(objId, pEntity);
    pBlockTable->close();
    pEntity->close();
    pSpaceRecord->close();
    return Acad::eOk;
    }

    Пример заказного режима объектной привязки

    Следующий пример демонстрирует создание заказных режимов объектной привязки:
    #include "rxobject.h"
    #include "ads.h"
    #include "adslib.h"
    #include "dbmain.h"
    #include "dbents.h"
    #include "dbosnap.h"
    #include "acedinpt.h"
    // Socket Osnap mode protocol extension class.
    //
    class AcmeSocketInfo : public AcDbCustomOsnapInfo {
    public:
    ACRX_DECLARE_MEMBERS(AcmeSocketInfo);
    virtual Acad::ErrorStatus
    getOsnapInfo(
    AcDbEntity* pickedObject,
    int gsSelectionMark,
    const AcGePoint3d& pickPoint,
    const AcGePoint3d& lastPoint,
    const AcGeMatrix3d& viewXform,
    AcArray& snapPoints,
    AcArray& geomIdsForPts,
    AcArray& snapCurves,
    AcArray& geomIdsForLines)
    };
    // This class is registered with AcRx, to be used by the host
    // application to look up entity class-specific implementations.
    //
    ACRX_NO_CONS_DEFINE_MEMBERS(AcmeSocketInfo,AcDbCustomOsnapInfo);
    Acad::ErrorStatus
    AcmeSocketInfo::getOsnapInfo(
    AcDbEntity*,
    int,
    const AcGePoint3d&,
    const AcGePoint3d&,
    const AcGePoint3d&,
    AcArray& snapPoints,
    AcArray& geomIdsForPts,
    AcArray& snapCurves,
    AcArray& geomIdsForLines)
    {
    // Associate with AcDbEntity to define default behavior.
    //
    snapPoints.setLogicalLength(0);
    geomIdsForPts.setLogicalLength(0);
    snapLiness.setLogicalLength(0);
    geomIdsForLines.setLogicalLength(0);
    }
    // Socket Osnap mode protocol extension object for AcDbLine.
    //
    class AcmeSocketForLine : public AcmeSocketInfo {
    public:
    virtual Acad::ErrorStatus
    getOsnapInfo(
    AcDbEntity* pickedObject,
    int gsSelectionMark,
    const AcGePoint3d& pickPoint,
    const AcGePoint3d& lastPoint,
    const AcGeMatrix3d& viewXform,
    AcArray& snapPoints,
    AcArray& geomIdsForPts,
    AcArray& snapCurves,

    // If this ASSERT fails, then the pixel size is really position-
    // dependent.
    //
    ASSERT(!vportDrawContext->viewport()->isPerspective());
    vportDrawContext->viewport()->getNumPixelsInUnitSquare(AcGePoint3d::kOrigin, pixelArea);
    double halfGlyphSizeInDCS =
    acdbCustomOsnapManager->osnapGlyphSize() * pixelArea.x / 2.0;
    // Draw an asterisk with 4 segments.
    //
    sSegmentPoints[0].set(
    mCurDCSLoc.x-halfGlyphSizeInDCS,
    mCurDCSLoc.y-halfGlyphSizeInDCS, 0.0);
    sSegmentPoints[1].set(
    mCurDCSLoc.x+halfGlyphSizeInDCS,
    mCurDCSLoc.y+halfGlyphSizeInDCS, 0.0);
    vportDrawContext->geometry().polylineDc( 2, &(sSegmentPoints[0]));
    sSegmentPoints[0].set(
    mCurDCSLoc.x-halfGlyphSizeInDCS,
    mCurDCSLoc.y+halfGlyphSizeInDCS, 0.0);
    sSegmentPoints[1].set(
    mCurDCSLoc.x+halfGlyphSizeInDCS,
    mCurDCSLoc.y-halfGlyphSizeInDCS, 0.0);
    vportDrawContext->geometry().polylineDc( 2, &(sSegmentPoints[0]));
    sSegmentPoints[0].set(
    mCurDCSLoc.x-halfGlyphSizeInDCS,
    mCurDCSLoc.y, 0.0);
    sSegmentPoints[1].set(
    mCurDCSLoc.x+halfGlyphSizeInDCS,
    mCurDCSLoc.y, 0.0);
    vportDrawContext->geometry().polylineDc( 2, &(sSegmentPoints[0]));
    sSegmentPoints[0].set(
    mCurDCSLoc.x,
    mCurDCSLoc.y-halfGlyphSizeInDCS, 0.0);
    sSegmentPoints[1].set(
    mCurDCSLoc.x,
    mCurDCSLoc.y+halfGlyphSizeInDCS, 0.0);
    vportDrawContext->geometry().polylineDc( 2, &(sSegmentPoints[0]));
    };
    AcmeSocketGlyph* pSocketGlyph = NULL;
    // Master object for the socket custom Osnap mode.
    //
    class AcmeSocketMode : public AcDbCustomOsnapMode {
    public:
    virtual const char*
    localModeString() const {return "SOCket"};
    virtual const char*
    globalModeString() const {return "SOCket"};
    virtual const AcRxClass*
    entityOsnapClass() const {return AcmeSocketInfo::desc());
    virtual AcGiGlyph*
    glyph() const {return pSocketGlyph;);
    virtual const char*
    tooltipString() const {return "Socket to Me?" };
    };
    static AcmeSocketMode* pSocketMode = NULL;


    /* ================ ObjectARX application interface ============ */
    AcRx::AppRetCode
    acrxEntryPoint(AcRx::AppMsgCode msg, void*)
    {
    switch(msg) {
    case AcRx::kInitAppMsg:
    // Register the class.
    //
    AcmeSocketInfo::rxInit();
    acrxBuildClassHierarchy();
    pDefaultSocketInfo = new AcmeSocketInfo;
    AcDbEntity::desc()->addX(AcmeSocketInfo::desc(),
    pDefaultSocketInfo);
    pSocketForLine = new AcmeSocketForLine;
    AcDbLine::desc()->addX(AcmeSocketInfo::desc(), pSocketForLine);
    //-- };
    // Create the glyph object to be returned by the socket
    // mode object.
    //
    pSocketGlyph = new AcmeSocketGlyph;
    // Create and register the custom Osnap Mode
    pSocketMode = new AcmeSocketMode;
    acdbCustomOsnapManager->addCustomOsnapMode(pSocketMode);
    // The SOCket Osnap mode is now plugged in and ready to use.
    //
    break;
    case AcRx::kUnloadAppMsg:
    // Clean up.
    acdbCustomOsnapManager->removeCustomOsnapMode(pSocketMode);
    delete pSocketMode;
    // Unregister, then delete the protocol extension object.
    //
    AcDbEntity::desc()->delX(AcmeSocketInfo::desc());
    delete pDefaultSocketInfo;
    AcDbLine::desc()->delX(AcmeSocketInfo::desc());
    delete pSocketForLine;
    // Remove the protocol extension class definition.
    //
    acrxClassDictionary->remove("AcmeSocketInfo");
    break;
    default:
    // Between the initialization and termination of the
    // application, all registered objects will be directly
    // invoked as needed. No commands or AutoLISP
    // expressions are necessary.
    //
    break;
    }
    return AcRx::kRetOK;
    }

    Примеры Преобразования

    AcGiViewport класс обеспечивает функции, которые дают Вам, обращаются к графическому конвейеру, позволяя Вам применить каждое преобразование явно и исполняют математику самостоятельно. Если Вы управляете примитивами в графическом конвейере самостоятельно, Вы используете различные формы AcGi многоугольника и полилинии в зависимости от того, где Вы находитесь в графическом конвейере.
    AcGiViewportGeometry класс обеспечивает три формы для многоугольников и полилиний, в модели, глазе, и координатах дисплея. Обычно, Вы использовали бы polyline() и polygon () функции, которые требуют модельных координат.
    Используйте polylineEye () и polygonEye () если Вы собираетесь работать с координатами глаза, как показано в Примерах 1 и 2. Используйте polygonDc () и polylineDc () если Вы работаете с координатами дисплея.
    Следующие разделы содержат четыре примера. Первый пример рисует тот же самый примитив, используя модель, глаз, и координаты дисплея. Его основная цель состоит в том, чтобы демонстрировать, как применить каждое преобразование в графическом конвейере. Второй пример иллюстрирует работу к координатам глаза, чтобы определить переднюю сторону и невидимые поверхности пирамиды. Третий пример иллюстрирует работу к координатам дисплея, чтобы рисовать примитив в размере относительно размера текущего окна. Четвертый пример показывает, как определить полилинию с наименьшим количеством долей, который является визуально неразличимым от один с больше доли.

    Следующие ObjectARX примеры состоят из

    Следующие ObjectARX примеры состоят из двух функций: createXrecord () и listXrecord (). Первая функция добавляет новый xrecord к словарю, добавляет словарь к словари имен объектов, и затем добавляет данные к xrecord. ListXrecord () функция открывает xrecord, получает его список данных, и посылает список, который будет напечатан.
    void
    createXrecord()
    {
    AcDbDictionary *pNamedobj, *pDict;
    acdbHostApplicationServices()->workingDatabase()
    ->getNamedObjectsDictionary(pNamedobj, AcDb::kForWrite);
    // Check to see if the dictionary we want to create is
    // already present. If not, then create it and add
    // it to the named object dictionary.
    //
    if (pNamedobj->getAt("ASDK_DICT", (AcDbObject*&) pDict,
    AcDb::kForWrite) == Acad::eKeyNotFound)
    {
    pDict = new AcDbDictionary;
    AcDbObjectId DictId;
    pNamedobj->setAt("ASDK_DICT", pDict, DictId);
    }
    pNamedobj->close();
    // Add a new xrecord to the ASDK_DICT dictionary.
    //
    AcDbXrecord *pXrec = new AcDbXrecord;
    AcDbObjectId xrecObjId;
    pDict->setAt("XREC1", pXrec, xrecObjId);
    pDict->close();
    // Create a resbuf list to add to the xrecord.
    //
    struct resbuf *pHead;
    ads_point testpt = {1.0, 2.0, 0.0};
    pHead = acutBuildList(AcDb::kDxfText,
    "This is a test Xrecord list",
    AcDb::kDxfXCoord, testpt,
    AcDb::kDxfReal, 3.14159,
    AcDb::kDxfAngle, 3.14159,
    AcDb::kDxfColor, 1,
    AcDb::kDxfInt16, 180,
    0);
    // Add the data list to the xrecord. Notice that this
    // member function takes a reference to resbuf, NOT a
    // pointer to resbuf, so you must dereference the
    // pointer before sending it.
    //
    pXrec->setFromRbChain(*pHead);
    acutRelRb(pHead);
    pXrec->close();
    }
    // Gets the xrecord associated with the key XREC1 and
    // lists out its contents by passing the resbuf list to the
    // function printList.
    //
    void
    listXrecord()
    {
    AcDbDictionary *pNamedobj;
    acdbHostApplicationServices()->workingDatabase()
    ->getNamedObjectsDictionary(pNamedobj, AcDb::kForRead);
    // Get the dictionary object associated with the key ASDK_DICT.
    //
    AcDbDictionary *pDict;
    pNamedobj->getAt("ASDK_DICT", (AcDbObject*&)pDict,
    AcDb::kForRead);
    pNamedobj->close();
    // Get the xrecord associated with the key XREC1.
    //
    AcDbXrecord *pXrec;
    pDict->getAt("XREC1", (AcDbObject*&) pXrec,
    AcDb::kForRead);
    pDict->close();
    struct resbuf *pRbList;
    pXrec->rbChain(&pRbList);
    pXrec->close();
    printList(pRbList);
    acutRelRb(pRbList);
    }

    Принятие параметров в функциях обратного вызова

    В функции повторного вызова, значение и данные отобранного неперекрывающего расположения пропускают как параметр пакета повторного вызова, как показано на определении функции повторного вызова более раннего примера:
    static void CALLB accept_OK(ads_callback_packet *cpkt)
    {
    // DLGOK == User pressed OK.
    //
    ads_done_dialog(cpkt->dialog, DLGOK);
    }
    CALLB символ, который появляется перед именем функции,  определен как пробел.
    Это - просто маркер, чтобы делать это проще для Вас, чтобы расположить функции повторного вызова, когда Вы поддерживаете вашу программу. Однако, Вы должны всегда использовать это в случае, если это определено по-другому в будущем выпуске.
    Предшествующий пример просто закрывает диалоговое окно, используя только один из параметров в пакете. Тип данных пакета повторного вызова определен следующей инструкцией:
    typedef struct {
    ads_hdlg dialog;
    ads_htile tile;
    char *value;
    void *client_data;
    int reason;
    long x, y;
    } ads_callback_packet;
    Параметры прошли в пакете, имеют следующие цели:
    !!!!     Неперекрывающее расположение  ßreà  tile


    dialog

    Метка диалогового окна.

    tile

    Метка отобранного неперекрывающего расположения. Вместо принятия ключа отобранного  неперекрывающего расположения, пакет PDB передает функции повторного вызова метку неперекрывающего расположения (типа ads_htile). Вы используете метку, чтобы отыскать атрибуты неперекрывающего расположения, включая его ключ, вызывая функцию ads_get_attr_string () (. Ads_get_attr_string () функция не имеет копии AutoLISP.)

    value

    Строка, которая содержит значение отобранного неперекрывающего расположения. Пространство для этой строки управляется в соответствии с AutoCAD; обращайтесь с этим как только для чтения. Если Вы должны изменить значение неперекрывающего расположения, используйте ads_set_tile (). Если неперекрывающее расположение - список (или всплывающий список) и никакой элемент не отобран, строка значения пуста (" ").

    client_data

    Указатель на специфичные для приложения данные, который был инициализирован ads_client_data_tile (). Если не имеется никаких клиентских данных, это - NULL.

    reason

    Причина для повторного вызова. Это зависит, на ч действии пользователь брал. Его значение установлено для любого действия, но Вы должны осмотреть это только, когда действие связано с edit_box, list_box, image_button, или неперекрывающим расположением слайдера.

    x, y

    Когда пользователь выбирает кнопку изображения, они установлены в (X, Y) отобранные координаты. Координаты - координаты неперекрывающего расположения в пределах диапазона, который ads_dimensions_tile () возвратился бы для кнопки изображения.

    Например, чтобы отыскать ключ отобранного неперекрывающего расположения, функция повторного вызова могла включать следующий код:
    char newtile[TILE_STR_LIMIT];
    ads_get_attr_string(cpkt->tile, "key", newtile, TILE_STR_LIMIT);
    При поиске строкового значения, убедитесь, что разместили пространство для строки. Этот пример определяет строковую длину,  используя константу TILE_STR_LIMIT.
    Ads_get_attr_string () функция может отыскивать другие атрибуты со значением таким же образом, что этот пример отыскивает ключ.

    Принятие указения точки командой AutoCAD

    Некоторые команды AutoCAD (типа TRIM, EXTEND и FILLET) требует, чтобы пользователи определили точку указки также как примитив. Чтобы передавать такие пары примитива и данных точки посредством acedCommand (), Вы должны определить имя примитива сначала и включать пару в RTLB и коды типа результата RTLE.
    Следующий типовой кодовый фрагмент создает круг, центрированный в (5,5) и линию, которая простирается от (1,5) до (8,5); это предполагает, что круг и линия созданы в пустом рисунке. Это тогда использует точку указки с командой TRIM, чтобы урезать линию в крае круга. AcdbEntNext () функция находит следующий примитив в рисунке, и acdbEntLast () функция находит последний примитив в рисунке.
    ads_point p1;
    ads_name first, last;
    acedCommand(RTSTR, "Circle", RTSTR, "5,5", RTSTR, "2", 0);
    acedCommand(RTSTR, "Line", RTSTR, "1,5", RTSTR, "8,5", RTSTR, "", 0);
    acdbEntNext(NULL, first); // Get circle.
    acdbEntLast(last); // Get line.
    // Set pick point.
    p1[X] = 2.0;
    p1[Y] = 5.0;
    p1[Z] = 0.0;
    acedCommand(RTSTR, "Trim", RTENAME, first, RTSTR, "",
    RTLB, RTENAME, last, RTPOINT, p1, RTLE,
    RTSTR, "", 0);

    Приостановка ввода пользователя

    Если команда AutoCAD происходит, и AutoCAD сталкивается с символом ПАУЗЫ как параметр к acedCommand () или acedCmd (), команда временно приостановлена, чтобы позволить прямой ввод пользователя, включая перемещение. Символ ПАУЗЫ состоит из строки, которая содержит одиночную наклонную черту влево. Это подобно наклонной черте влево механизм паузы, предусмотренный меню.
    Следующий запрос к acedCommand () вызывает команду ZOOM и затем использует символ ПАУЗЫ так, чтобы пользователь мог выбирать одну из опций ZOOM.
    result = acedCommand(RTSTR, "Zoom", RTSTR, PAUSE, RTNONE);
    Следующий запрос начинает команду CIRCLE, устанавливает среднюю точку как (5,5), и затем делает паузу, чтобы позволить пользователю перетаскивать радиус круга на экране. Когда пользователь определяет выбранную точку (или вводит выбранный радиус), функциональные резюме, тянущий линию от (5,5) до (7,5).
    result = acedCommand(RTSTR, "circle", RTSTR, "5,5",
    RTSTR, PAUSE, RTSTR, "line", RTSTR, "5,5", RTSTR,
    "7,5", RTSTR, "", 0);

    Проблемы длинных транзакций для объектов пользователя

    Длинные транзакции – метод борьбы против обычных проблем, следующих из объектов, которые не должны имитироваться, или меж-объектные ссылки, которые не обработаны.
    Если LongTransactionManager (LTM) находит, что это должно имитировать,  фильтрованный класс возражает против законченного длинную операционную отладку () или checkIn (), это прервет полную операцию. Если это находит AcDbSoftPointerId или AcDbHardPointerId, который не в имитации IdMap, это также прервется.
    Приложения, которые должны предотвратить их объекты от включения как имитируется в длинных трудах, должны регистрировать те объекты, использующие AcApLongTransactionManager::addClassFilter () функция.
    AcDbProxyEntity и AcDbProxyObject всегда фильтруются, так когда приложение - не, подарок{*настоящее*}, все его объекты будет фильтрован автоматически.
    Wblock имитирующие маркеры{*дескрипторы*} все жесткие ссылки{*справочники*} указателя, но глубоко имитация не требует никакого типа ссылки{*справочников*}, которая будет отображена. Оба из этих типов имитации используются в длинных трудах, в зависимости от типа сделки, это. Если прикладные использования или этих типов ссылок{*справочников*}, или маркеров{*дескрипторов*} xdata, то его объекты будут отклонены от длинных трудов, если приложение берет дополнительные шаги, чтобы обработать ссылки{*справочники*}. Это означает, что, если приложение не загружено, то его объекты и ссылки{*справочники*} будут автоматически предотвращены от участия в длинных трудах, и любые данные должны сохраниться в его Отсутствие.
    Используйте длинные операционные и глубокие уведомления аналога, чтобы прервать имитацию их объекта и ссылок{*справочников*}, и добавляться необходима ли имитация объекта или отображение. См. глубокую документацию уведомления аналога и выборки для получения дополнительной информации на этом.
    Если объект с мягкой ссылкой{*справочниками*} указателя имитируется (или жесткая ссылка{*справочники*} указателя в глубоком аналоге), приложение должно удостовериться, что ссылка{*справочники*} ИДЕНТИФИКАТОР находится в IdMap, или как отображенная пара ИДЕНТИФИКАТОРА, или имитируемая пара ИДЕНТИФИКАТОРА. Отображения обычно используются, когда объекты обращаются{*относятся*} к некоторому общему{*обычному*} словарю, который приложение обслуживает{*поддерживает*} в пределах рисунка. В глубоком аналоге, отображение может состоять из IdPair, где key = value. В аналоге wblock между рисунками, IdPair отобразил бы словарь одной базы данных со словарем другой базы данных.

    Ссылка{*справочники*} имитируется приложением, используя или deepClone () или wblockClone () от повторного вызова уведомления.

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

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

    Имеются некоторые примеры:

    § если приложение знает, относительно, которые объекты упомянуты, но не будут имитироваться — в beginWblockObjects (), beginDeepClone (), или beginCheckOut () уведомление —, они могут прибавлять объект ID упомянутого объекта к IdMap для имитации. Рекомендуемый подход состоит в том, чтобы установить значение в NULL, и idPair как не имитируемый. Например idMap.assign (idPair (идентификатор, AcDbObjectId:: kNull, kFalse); Если объект должен имитироваться позже, idPair будет изменен{*заменен*} соответственно.


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

    § если ссылка{*справочники*} - компонент данных объекта, который зарегистрирован из использования dwgOutFields (), тогда может быть возможно избежать длинного операционного испытания законности. Испытание сделано,  регистрируя из ИДЕНТИФИКАТОРОВ, использующих тип kIdFiler регистратора. Чтобы избегать испытания, делайте не файл из ИДЕНТИФИКАТОРОВ, которые не должны имитироваться, в течение этого типа записи в файл. Однако, не проведите{*держите*} никакое монопольное использование ИДЕНТИФИКАТОРАМИ из этой записи в файл, или других особенностей, которые используют этого регистратора, подобно частичному сохраняют{*экономят*} и загружают, не может должным образом обрабатывать ваши объекты. Единственные безопасные ИДЕНТИФИКАТОРЫ, чтобы отказать от этого регистратора - объекты AcDbSoftPointerId и AcDbHardPointerId.

    § если ИДЕНТИФИКАТОР - фактически в постоянном реакторе, возможно найти это, используя реактор iterator. Имеется пример того, как объект словаря находит и прибавляет его ИДЕНТИФИКАТОР к IdMap в течение beginWblockClone () уведомление.

    beginWblockClone(..., AcDbIdMapping& idMap)

    {

    ...

    AcDbDictionaryIterator* pIter = pDict->newIterator();

    AcDbObject* pObj;

    for ( ; !pIter->done(); pIter->next()) {

    acdbOpenObject(pObj, pIter->objectId(), kForRead);

    AcDbVoidPtrArray* pReactors = pObj->reactors();

    void* pReactor;

    AcDbObjectId rId;

    MyReactor* pMyReactor;

    if (pReactors) {

    for (int i = 0; i < pReactors->length(); i++) {

    pReactor = pReactors->at(i);

    if (acdbIsPersistentReactor(pReactor)) {

    rId = acdbPersistentReactorObjectId(pReactor);

    if (acdbOpenObject(pMyReactor, rId, kForRead) == eOk) {

    pMyReactor->close();

    AcDbIdPair idPair(rId,

    AcDbObjectId::kNull, kFalse);

    idMap.assign(idPair);

    }

    }

    }

    }

    pObj->close();

    }

    delete pIter;

    pDict->close();

    }

    Прокси-объект для пользователя

    Сообщение AutoCAD уведомляет пользователей относительно создания прокси-объектов. Пользователи могут читать относительно прокси-примитивов, использующих команду LIST. Они могут также сталкиваться с прокси-объектами из-за способа,  которым примитивы отображены и путь, которым они отвечают на редактирование.
    AutoCAD отображает сообщение немедленно после любой команды, которая заставляет прокси-объект быть созданной (например, DXFIN, XREF, ВСТАВЛЯТЬ). Сообщение включает число прокси-примитивов, созданных с визуальным представлением, число созданных прокси-примитивов, который не может быть отображен из-за отсутствия родительского приложения, и числа прокси-объектов, созданных без визуального представления.
    Операция LIST, выполненная на прокси-объекте идентифицирует приложение, которое создавало заказной объект, и идентифицирует объект как являющийся или типа ACAD_PROXY_OBJECT или ACAD_PROXY_ENTITY.
    Пользователи могут управлять дисплей прокси-объектов с PROXYSHOW
    переменной системы, которая имеет следующие опции:
    1 Ни один показанный
    2 Графическое представление
    3 Границы поля

    Путь Подпримитива

    Путь подпримитива уникально идентифицирует подпримитив в пределах специфического примитива в рисунке. Этот путь, класса AcDbFullSubentPath, состоит из массива объекта IDs и объекта ID подпримитива:
    {              AcDbObjectIdArray mObjectIds;
    AcDbSubentId mSubentId;
    }
    Массив содержит объект IDs, которые определяют путь к “основному” примитиву.
    Например, блочная ссылка{*справочники*} (примитив, что ссылки{*справочники*} блочный отчет{*запись*} таблицы) могли бы содержать два поля, каждый из типа AcDb3dSolid. Массив объектов ID содержит два входа: ИДЕНТИФИКАТОР блочной ссылки{*справочников*}, сопровождаемой ИДЕНТИФИКАТОРОМ основного примитива [InsertID, SolidID].
    Второй элемент AcDbFullSubentPath - объект AcDbSubentId, который имеет тип подпримитива (вершина, край, или лицо) и индекс подпримитива в списке. Используйте тип функций AcDbSubentId () и index() чтобы обратиться к данным члена.
    Используя предыдущий пример, второй край твердых будет иметь его AcDbFullSubentPath как
    {(InsertID, solid1ID)
    (kEdgeSubentType, 2)};
    Если бы Вы имеете твердый только, AcDbFullSubentPath был бы следующим образом для первого
    лица твердых.
    {(solidID)
    (kFaceSubentType, 1)};

    Путь поиска файлов

    Если Вы не определяете,  путь поиска файлов, загружая функции типа arxload ищет приложение в каталогах, указанных путем библиотеки AutoCAD.
    Путь библиотеки AutoCAD включает следующие каталоги в показанном  порядке:
  • текущий каталог.

  • каталог, который содержит файл текущего рисунка.

  • каталоги, указанные путем поддержки (см. Руководство Настройки AutoCAD).

  • каталог, который содержит программные файлы AutoCAD.


  • Расчленение примитивов

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

    Взрыв примитивов

    Entity
    By Itself
    Nonuniform Scaling
    (when in a block)
    AcDb3dSolid
    Regions,bodies
    NA; can’t be exploded
    AcDbBody
    Regions, bodies
    NA
    Ac2dDbPolyline
    Lines, arcs
    Self/NA
    Ac3dPolyline
    Lines
    Self
    AcDbArc
    Self
    Ellipse
    AcDbCircle
    Self
    Ellipse
    AcDbDimension
    Solids, lines, text,strings, points
    NA
    AcDbEllipse
    Self
    Self
    AcDbLeader
    Self
    NA
    AcDbLine
    Self
    Self
    AcDbRay
    Self
    Self
    AcDbSpline
    Self
    Self
    AcDbXline
    Self
    Self
    AcDbFace
    Self
    Self
    AcDbMline
    Lines
    Self
    AcDbMText
    One text entity for each line
    Self
    AcDbPoint
    Self
    Self
    AcDbPolyFaceMesh
    AcDbFace
    Self
    AcDbPolygonMesh
    Self
    Self
    AcDbRegion
    Curves (splines, lines,
    arcs, circles)
    NA
    AcDbShape
    Self
    Self
    AcDbSolid
    Self
    Self
    AcDbText
    Self
    Self
    AcDbTrace
    Self
    Self

    Explode()  - функция только для чтения, которая не изменяет первоначальный примитив. Это возвращает набор примитивов для приложения, чтобы обработать как желательно. Одно потенциальное использование этой функции должно взорвать сложный примитив, чтобы произвести более простые примитивы и затем работать на тех примитивах. Например, если Вы осуществляли intersectForPoints () функция для ломаной линии, могло бы быть проще имеет дело с индивидуальные части ломаной линии скорее чем законченный примитив.
    Следующие инструкции истинны для команды EXPLODE (но не для функции explode ()):
    § Визуальное появление{*вид*} постоянный.
    § взрываемый примитив стерт от базы данных.
    § Одни или более новые примитивы созданы и добавлены в конец к базе данных.


    Распространение AutoCAD Встроенные Диалоги Позиции табуляции

    Мастер Класса Использования или некоторые другие средства, чтобы создать вашу позицию табуляции, подклассифицируемую от CDIALOG. В свойствах для диалога, измените{*замените*} стиль диалога, чтобы “всплыть” и границу к “изменению размеров”. Осуществьте перегрузку для PostNcDestroy (). Замените все возникновения CDIALOG с CACUITABEXTENSION во всех исходных файлах для диалога. В PostNcDestroy () для расширения{*продления*} позиции табуляции удаляют объект позиции табуляции, который был распределен (см. пример ниже).
    В вашем AcRx:: kInitAppMsg обработчик в acrxEntryPoint () добавляют запрос к acedRegisterExtendedTab ("MYAPPNAME.ARX", "DIALOGNAME"), где MYAPPNAME - основное имя файла вашего приложения, и DIALOGNAME - изданное имя расширяемого табулированного диалога, к которому Вы желаете добавить.
    Осуществьте AcRx:: kInitDialogMsg обработчик в acrxEntryPoint () и добавьте позицию табуляции там. (Пусто *) appId параметр к acrxEntryPoint () - указатель CAcUiTabExtensionManager. Используйте функцию GetDialogName члена () для CACUITABEXTENSIONMANAGER, чтобы получить имя инициализируемого диалога и, если приложение хочет добавить к этому диалогу, назовите AddTab () функцией члена CACUITABEXTENSIONMANAGER, чтобы добавить позицию табуляции. Один параметр к этой функции - указатель на предварительно распределенный объект CAcUiTabExtension. Если диалог изменяемого размера, и Вы хотите некоторых из вашего средства управления, чтобы изменять размеры, добавить что изменение размеров кода после запроса к AddTab ().
    Например
    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;
    case AcRx::kInitDialogMsg:
    // A dialog is initializing that we are interested in adding
    // tabs to.
    addMyTabs((CAcUiTabExtensionManager*)pkt);

    break;

    default:

    break;

    }

    return AcRx::kRetOK;

    }

    void initApp()

    {

    InitMFC();

    // Do other initialization tasks here.

    acedRegCmds->addCommand(

    "MYARXAPP",

    "MYARXAPP",

    "MYARXAPP",

    ACRX_CMD_MODAL,

    &MyArxAppCreate);

    // Here is where we register the fact that we want to add

    // a tab to the PREFERENCES dialog.

    acedRegisterExtendedTab("MYARXAPP.ARX", "PREFERENCES");

    }

    // CMyTab1 is subclassed from CAcUiTabExtension.

    static CMyTab1* pTab1;

    void addMyTabs(CAcUiTabExtensionManager* pXtabManager)

    {

    // Allocate an extended tab if it has not been done already

    // and add it through the CAcUiTabExtensionManager.

    pTab1 = new CMyTab1;

    pXtabManager->AddTab(_hdllInstance, IDD_TAB1,

    "My Tab1", pTab1);

    // If the main dialog is resizable, add your control

    // resizing directives here.

    pTab1->StretchControlXY(IDC_EDIT1, 100, 100);

    }

    Тогда для CMYTAB1 выполнения класса:

    void CMyTab1::PostNcDestroy()

    // Override to delete added tab.

    {

    delete pTab1;

    pTab1 = NULL;

    CAcUiTabExtension::PostNcDestroy();

    }

    Расширение протокола pеализации

    Осуществлять расширение протокола
    1 Объявляют и определяют классы расширения протокола, которые включают дополнительные функциональные возможности.
    2 Регистрируют классы расширения протокола с приложением, и связывают их с классами ObjectARX, к которым они добавляют функциональные возможности.
    Эти шаги описаны подробно в следующих двух подразделах. Дополнительная информация относительно проблем выполнения следует за этими секциями.

    Расширенные данные примитива

    Регистрация Расширенных Данных Примитива (EED) поддержана в ObjectDBX. Несколько незначительных различий от ObjectARX API существуют, однако. Чтобы использовать EED, приложение должно быть зарегистрировано с базой данных. В ObjectARX API, acdbRegApp () функция наиболее вероятно использовалась бы. Этот интерфейс не поддержан в ObjectDBX, так что альтернативные функции для регистрации приложения и имеющий дело resbuf цепочки описаны здесь.
    Чтобы регистрировать ваше приложение, используйте функции AcDbDatabase, чтобы получить regapp таблицу, и добавлять запись:
    registerApplication(AcDbDatabase* pDatabase)
    {
    AcDbRegAppTable *pRegAppTable;
    AcDbObjectId blockId;
    if (pDatabase->getRegAppTable(pRegAppTable, AcDb::kForWrite) == Acad::eOk)
    {
    AcDbRegAppTableRecord *pRecord = new AcDbRegAppTableRecord;
    if (pRecord)
    {
    pRecord->setName("ACDBTEST_APP"); // For example
    if (pRegAppTable->add(blockId, pRecord) == Acad::eOk)
    pRecord->close();
    else
    delete pRecord;
    }
    pRegAppTable->close();
    }
    }
    EED добавлен к AcDbEntity как
    resbuf цепочка. При использовании resbuf типы, которые требуют, указатели (подобно resval.rstring), убеждаются, что разместили указатель с acdbAlloc () функция, и удалили это с acdbFree () функция ( Объявляемый в dbmain.h файле).

    Расширенные Данные

    Расширенные{*продленные*} данные (xdata) созданы приложениями, написанными с ObjectARX или AutoLISP и могут быть добавлены к любому объекту. Xdata состоит из списка связей resbufs, используемого приложением. (AutoCAD обслуживает{*поддерживает*} информацию, но не использует это.) данные связаны с кодом группы DXF в диапазоне от 1000 до 1071.
    Этот механизм пространствено - эффективен и может быть полезен для добавления легких данных к объекту. Однако, xdata ограничен 16КБ и существующим набором кодов группы DXF и напечатает.
    Для более детального описания xdata, см. Руководство Настройки AutoCAD.
    Используйте AcDbObject:: xData () функция, чтобы получить resbuf цепочку, содержащую копию xdata для объекта:
    virtual resbuf*
    AcDbObject::xData(const char* regappName = NULL) const;
    Используйте AcDbObject:: setXData () функция, чтобы определить xdata для объекта:
    virtual Acad::ErrorStatus
    AcDbObject::setXData(const resbuf* xdata);
    Следующий пример использует xData () функция, чтобы получить xdata для выбранного объекта и затем печатает xdata на экран. Это тогда прибавляет строку (testrun) к xdata и называет setXdata () функцией, чтобы изменить xdata объекта. Этот пример также иллюстрирует использование upgradeOpen () и downgradeOpen () функции.
    // Эта функция называет selectObject () функцией, чтобы позволить
    // пользователю выбирать объект; тогда это обращается к xdata объекта
    // и посылает список printList () функцию, которая перечисляет значения resval и restype.
    //
    void
    printXdata()
    {
    // Select and open an object.
    //
    AcDbObject *pObj;
    if ((pObj = selectObject(AcDb::kForRead)) == NULL) {
    return;
    }
    // Get the application name for the xdata.
    //
    char appname[133];
    if (acedGetString(NULL,
    "\nEnter the desired Xdata application name: ",
    appname) != RTNORM)
    {
    return;
    }
    // Get the xdata for the application name.
    //
    struct resbuf *pRb;
    pRb = pObj->xData(appname);
    if (pRb != NULL) {
    // Print the existing xdata if any is present.

    // Notice that there is no -3 group, as there is in

    // LISP. This is ONLY the xdata, so

    // the -3 xdata-start marker isn’t needed.

    //

    printList(pRb);

    acutRelRb(pRb);

    } else {

    acutPrintf("\nNo xdata for this appname");

    }

    pObj->close();

    }

    void

    addXdata()

    {

    AcDbObject* pObj = selectObject(AcDb::kForRead);

    if (!pObj) {

    acutPrintf("Error selecting object\n");

    return;

    }

    // Get the application name and string to be added to

    // xdata.

    //

    char appName[132], resString[200];

    appName[0] = resString[0] = ’\0’;

    acedGetString(NULL, "Enter application name: ",

    appName);

    acedGetString(NULL, "Enter string to be added: ",

    resString);

    struct resbuf *pRb, *pTemp;

    pRb = pObj->xData(appName);

    if (pRb != NULL) {

    // If xdata is present, then walk to the

    // end of the list.

    //

    for (pTemp = pRb; pTemp->rbnext != NULL; pTemp = pTemp->rbnext)

    { ; }

    } else {

    // If xdata is not present, register the application

    // and add appName to the first resbuf in the list.

    // Notice that there is no -3 group as there is in

    // AutoLISP. This is ONLY the xdata so

    // the -3 xdata-start marker isn’t needed.

    //

    acdbRegApp(appName);

    pRb = acutNewRb(AcDb::kDxfRegAppName);

    pTemp = pRb;

    pTemp->resval.rstring

    = (char*) malloc(strlen(appName) + 1);

    strcpy(pTemp->resval.rstring, appName);

    }

    // Add user-specified string to the xdata.

    //

    pTemp->rbnext = acutNewRb(AcDb::kDxfXdAsciiString);

    pTemp = pTemp->rbnext;

    pTemp->resval.rstring

    = (char*) malloc(strlen(resString) + 1);

    strcpy(pTemp->resval.rstring, resString);

    // The following code shows the use of upgradeOpen()

    // to change the entity from read to write.

    //

    pObj->upgradeOpen();

    pObj->setXData(pRb);

    pObj->close();

    acutRelRb(pRb);

    }

    Растровые Изображения

    Если Вы желаете записать приложение ObjectDBX, которое управляет растровыми примитивами, Вы должны сначала связаться с Модулем Поддержки Отображения (ISM) DBX, затем иметь ваше приложение, явно загружают это DBX файл перед попыткой вызвать любой из растровых API. Например, если Вы использовали AutoCAD LT уровень поддержки ACIS, включаете этот запрос:
    AcRxDynamicLinker- > loadModule ("acIsmobj.dbx");
    Если Вы читаете DWG файл, который содержит растровые примитивы, ObjectDBX будет пытаться загружать acIsmObj.dbx после столкновения с AcDbRasterImage примитивом в чертежном файле. ObjectDBX будет только искать сохраненный путь загрузочный модуль.
    Это отличается от AutoCAD, который кроме того ищет путь поиска файлов AutoCAD.
    Помните, что читатели Двигателя Изображения (ie*rd.dll, в этом случае) должны быть в том же самом каталоге как ism*.dbx файлы. Это не достаточно для этих файлов, чтобы быть на пути поиска файлов; вместо этого они должны быть в том же самом местоположении как ism*.dbx. Это поведение соответствует таковому AutoCAD.

    Разблокировка приложения

    По умолчанию, приложения блокированы и не могут быть разгружены. Чтобы быть классифицирован как “незагружаемое” приложение, приложение должно гарантировать, что AutoCAD и другие приложения больше не обращаются{*относятся*} к любым объектам{*целям*}, или структурирует приложение,  определил. Прежде, чем Вы делаете приложение незагружаемым, быть очень осторожным, что никакие клиентские приложения не содержат активные указатели на любые объекты{*цели*} в вашем адресном пространстве. Для списка операций очистки приложение должно исполнить, чтобы быть незагружаемым, см. “ Подготовка к Разгрузке ” на странице 38.
    Если Вы хотите делать ваше приложение незагружаемым, Вы должны сохранить значение pkt параметра, посланного с AcRx:: kInitAppMsg. Pkt параметр будет использоваться unlockApplication () на. По умолчанию, прикладная программа блокирована. Если Вы разблокируете приложение, это может быть разгружено.
    Используйте следующий две функции, чтобы блокировать и разблокировать приложение:
    bool
    AcRxDynamicLinker::lockApplication(void* pkt) const;
    bool
    AcRxDynamicLinker::unlockApplication(void* pkt) const;
    Следующие функциональные проверки, действительно ли приложение блокировано:
    bool
    AcRxDynamicLinker::isApplicationLocked(const char* name) const;
    Аналогичные глобальные функции также обеспечиваются:
    bool
    acrxLockApplication(void* pkt);
    bool
    acrxUnlockApplication(void* pkt);
    bool
    acrxApplicationIsLocked(const char* modulename);

    Разгрузка ObjectARX Приложения

    Вы можете разгрузить приложение ObjectARX с любым из следующих методов (если это разблокировано):
  • Заставят приложение разгрузить запрос от другого приложения ObjectARX, используя AcRxDynamicLinker:: unloadModule ().

  • Используют диалоговое окно APPLOAD, определенное в премии AutoCAD, программируют loadapp.arx. Этот файл определяет интерфейс пользователя для Автошепелявящегося arxload и функций arxunload.

  • Используют функцию arxunload от Alisp.

  • Используют acedArxUnload () функция от ObjectARX.

  • Вводят команду ARX в командную строку AutoCAD и используют опцию Unload.


  • Разгрузка приложения

    Когда приложение разгружено, и соответствующие операции уборки были выполнены, заказные объекты, и примитивы преобразованы в прокси-объекты. Для этого, чтобы произойти, все классы пользователя должны быть удалены из ObjectARX в, разгружают время с deleteAcRxClass () функция. Для описания требований для создания приложения “ незагружаемый, ” см. главу 3, “ Основы ObjectARX-приложения. ”

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

    Различия AcGix от просмотра в AutoCAD

    Следующие особенности не поддержаны AcGix:
    §
    Явный порядок рисования
    § XREF
    § отсечение Блок-ссылки
    § Перспективные виды
    § отсечение впереди / назад Области просмотра
    § Комплексные linetypes
    § Lineweight
    § Графические стили
    § разработка шрифта текста TrueType

    Различия кода под прикладным контекстом выполнения

    Имеется множество различий между кодом, выполняющимся в прикладном контексте выполнения и коде в других контекстах. Различия описаны ниже:
    § Это - не часть состояния командного процессора любого определенного документа.
    § Это может активизировать различные документы без немедленно приостановки, хотя это должно закончить и возвращаться прежде, чем новый активный документ может обрабатывать его ввод.
    § переключение Документа заблокирован при запросе ввода пользователя, или через ActiveX или ObjectARX запросы ввода пользователя.
    § AutoLISP также заблокирован при запросе ввода пользователя в этом контексте.
    § В случаях немодальных диалогов и внешних сгенерированных процессом запросов ActiveX, код должен блокировать документы, включая текущий документ. Использование IACADDOCUMENT методов StartUndoMarker() и EndUndoMarker() применит kWriteLock к документу.
    § средство команды не может использоваться от прикладного контекста выполнения, определенно acedCommand() и acedCmd() функции.
    § AcApDocManager::sendStringToExecute() и AcApDocManager::activateDocument() методы изменяют активный документ, но не приостанавливают выполнение кода, выполняющегося под прикладной контекст. Они приостановят выполнение кода, выполняющегося в контексте выполнения документа. AcApDocManager::sendStringToExecute() метод будет всегда очередь строка когда вызвано от прикладного контекста, при вызове, это от контекста документа будет или очередь строка, если активизирующийся параметр - kFalse, или немедленно приостанавливать контекст документа, если активизирующийся параметр - kTrue.

    Различия между ObjectDBX и ObjectARX

    Наиболее видимое различие между ObjectDBX и ObjectARX-приложениями - присутствие AutoCAD. ObjectDBX
    может использоваться, чтобы создать DBX файлы, которые будут работать с любым ведущим приложением, но ObjectARX-приложения всегда требуют AutoCAD как их ведущее приложение. ObjectDBX
    может также использоваться, чтобы создать ведущие приложения, но ObjectARX не может использоваться, чтобы создать ведущие приложения.
    ObjectDBX и ObjectARX
    доля библиотек большинство того же самого основания кода C++ имели обыкновение разрабатывать AutoCAD. Однако, ObjectDBX не использует функции ObjectARX, определенные на сессию рисунка AutoCAD, и некоторые из тех функций имеют замены в ObjectDBX, которые восполняют отсутствие во время выполнения AutoCAD.
    Типовые программы, включенные с ObjectDBX иллюстрируют различные использования ObjectDBX библиотек. Выборка creatent - самое простое и лучшее место, чтобы начать изучать развитие приложения ObjectDBX.
    Следующие секции обеспечивают детальную информацию относительно различий между ObjectARX и ObjectDBX библиотеками.

    Реакторные Классы

    Реакторные классы получены из AcRxObject, не AcDbObject. Поскольку эти реакторы - не, объекты базы данных, монопольное использование не обращаются к ним, и они не имеют объект IDs.
    Различные виды реакторов получают различные типы событий уведомления. Реактор базы данных (полученный из AcDbDatabaseReactor) получает события, связанные с состоянием базы данных — например, когда объект добавлен в конец к базе данных, изменяется в базе данных, или стерт. Уведомитель реактора - база данных, так что это добавлено к реакторному списку AcDbDatabase. Реактор объекта (полученный из AcDbObjectReactor) отвечает на события на объектном уровне, типа копирования, стирания, или изменения объект. Это может быть добавлено к реакторному списку любого AcDbObject. Редактор реактор (полученный из AcEditorReactor) отвечает на AutoCAD-специфичные события типа загрузки и разгрузки рисунка, старта или окончания команда, и другие виды взаимодействия пользователя. Объект AcEditor - единственный уведомитель для AcEditorReactor.
    Следующее - иерархия классов для реакторных классов:
    AcRxObject
    AcApDocManagerReactor
    AcApLongTransactionReactor
    AcDbDatabaseReactor
    AcDbObjectReactor
    AcDbEntityReactor
    AcDbRasterImageDefFileAccessReactor
    AcDbRasterImageDefTransReactor
    AcEdInputContextReactor
    AcRxDLinkerReactor
    AcRxEventReactor
    AcEditorReactor
    AcTransactionReactor

    Реакторы Транзакции

    Операционный менеджер имеет список реакторов, через которые это уведомляет клиентов относительно событий, уместных операционной модели. В настоящее время, имеются четыре события, которые посылают уведомление:
    virtual void
    transactionStarted( int& numTransactions);
    virtual void
    transactionEnded( int& numTransactions);
    virtual void
    transactionAborted( int& numTransactions);
    virtual void
    endCalledOnOutermostTransaction( int& numTransactions);
    Первые три уведомления обстреляны, когда любая транзакция, включая вложенные, начата, закончена, или прервана. Вы можете использовать эти уведомления в конъюнкции с
     AcTransactionManager::numActiveTransactions () чтобы определить транзакцию, которая является уместной уведомлению. Например, если запрос к AcTransactionManager::numActiveTransactions () возвращает нуль в
    Ваша перегрузка AcTransactionReactor:: transactionEnded () или AcTransactionReactor:: transactionAborted (), Вы знаете, что  наиболее удаленная транзакция заканчивается или прерывание выполнения.
    EndCalledOnOutermostTransaction () уведомление сообщает о начале передающегося{*совершающегося*} процесса всех модификаций, сделанных во всех транзакциях. Вы можете использовать этот повторный вызов, чтобы делать любую необходимую работу уборки прежде, чем передают{*совершают*}, начинает.
    Параметр во всех уведомлениях представляет число транзакций, которые являются активными плюс те, которые закончили успешно. Это не включает транзакции, которые были начаты и прерваны.

    Реализация deepClone() для заказных классов

    Первая часть этой главы описала основное использование deepCloneObjects () функция. Эта секция описывает скрытые подробности глубокого клонирования, так что Вы можете перегружать deepClone () и wblockClone () функции для ваших собственных заказных объектов и примитивов.
    При перегрузке этих функций для заказных объектов, Вы можете желать клонировать другие объекты с заказным объектом. Они упомянуты как зависимые ссылки.
    WblockClone заказного объекта () функция может вызывать wblockClone () на зависимой ссылке, но не должна вызвать deepClone ().
    Аналогично, deepClone заказного объекта () функция может вызывать deepClone () на зависимой ссылке, но не должна вызвать wblockClone (). Когда клонируемый запрос отправлен этим способом, Вы должны также отправить AcDbIdMapping образец, который был получен в запросе к клонируемой функции заказного объекта к клонируемой функции зависимого объекта. Никогда не создайте новый образец AcDbIdMapping, чтобы пройти к клонируемой функции зависимой ссылки.

    Реализация DWG Файловые Функции

    Если Вы осуществляете dwgOutFields () и dwgInFields () для нового класса, Вы должны сначала вызвать assertReadEnabled () или assertWriteEnabled () чтобы гарантировать, что объект открыт в правильном состоянии.
    Следующая вещь, которую ваш полученный класс должен делать, состоит в том, чтобы вызвать ту же самую функцию (например, dwgOutFields ()) на родительском классе. Этот процесс упомянут как передача сообщений высшего качества. Следующее - пример:
    AcDbDerivedClass:: dwgOutFields (...);
    {
    AssertReadEnabled ()
    MyParent:: dwgOutFields ();
    // Исполнить класс - определенные операции после супер-передачи сообщений.
    }
    Если Вы забываете вызывать соответствующее сообщение родительского класса, вы получите ошибку во время выполнения программы.
    После супер-передачи сообщений, Вы записываете или читаете поля. Вы можете улучшать выполнение,  проверяя тип регистратора. Например, если тип регистратора - kIdXlateFiler, и ваш класс не определяет любые связи ссылки, Вы можете просто возвращаться.
    С DWG файлами, Вы должны записывать и читать, вызывает тот же самый заказ{*порядок*}. Если запросы не соответствуют, получены, классы будут перепутаны. Если Вы имеете любые данные переменная-размера, помещаете индекс сначала.

    Реализация Функции точки растяжения

    Набор точек растяжения для объекта - часто подмножество его пунктов{*точек*} власти{*захвата*}. Когда пользователь вызывает команду STRETCH, getStretchPoints () функция используется, чтобы возвратить пункты{*точки*} протяжения, определенные для выбранного объекта. Для многих объектов, режим власти{*захвата*} и режим протяжения идентичен. Выполнение для AcDbEntity:: getStretchPoints () функция и AcDbEntity:: moveStretchPointsAt () функция должно вызвать ваш getGripPoints () и moveGripPointsAt () функции.
    Сигнатуры для функций протяжения
    virtual Acad::ErrorStatus
    AcDbEntity::getStretchPoints( AcGePoint3dArray& stretchPoints) const;
    virtual Acad::ErrorStatus
    AcDbEntity::moveStretchPointsAt(
    const AcDbIntArray& indices,
    const AcGeVector3d& offset);
    Вы не требуетесь, чтобы перегрузить getStretchPoints () и moveStretchPointsAt () функции AcDbEntity, потому что они значение по умолчанию к getGripPoints () и transformBy () функции.
    Заказной AsdkPoly класс перегружает эти функции как показано в примере в этом разделе. GetStretchPoints () функция возвращает вершину многоугольника, но не центр. MoveStretchPointsAt () функциональные проверки, были ли все пункты{*точки*} протяжения выбраны. Если они имеют, это вызывает transformBy () функция. Иначе, это вызывает moveGripPointsAt () функция.
    Acad::ErrorStatus
    AsdkPoly::getStretchPoints(
    AcGePoint3dArray& stretchPoints) const
    {
    assertReadEnabled();
    Acad::ErrorStatus es;
    if ((es = getVertices3d(stretchPoints)) != Acad::eOk)
    {
    return es;
    }
    // Remove the duplicate point at the start and end.
    //
    stretchPoints.removeAt(stretchPoints.length() - 1);
    return es;
    }
    Acad::ErrorStatus
    AsdkPoly::moveStretchPointsAt(
    const AcDbIntArray& indices,
    const AcGeVector3d& offset)
    {
    return moveGripPointsAt(indices, offset);
    }

    Реализация Функции точки захвата (grip)

    Объекты AutoCAD имеют точки захвата, которые появляются, когда пользователь выбирает объект устройством управления позицией. GetGripPoints () функция возвращает точки захвата, которые были определены для объекта.
    Сигнатуры для getGripPoints () и moveGripPointsAt () функции для AcDbEntity
    virtual Acad::ErrorStatus
    AcDbEntity::getGripPoints(
    AcGePoint3dArray& gripPoints,
    AcDbIntArray& osnapModes,
    AcDbIntArray& geomIds) const;
    virtual Acad::ErrorStatus
    AcDbEntity::moveGripPointsAt(
    const AcDbIntArray& indices,
    const AcGeVector3d& offset);
    OsnapModes и geomIds параметры getGripPoints () функция в настоящее время не используются.
    Режим Протяжения в редактировании власти{*захвата*} позволяет Вам протягивать объект,  перемещая выбранные власти{*захваты*} к новым местоположениям. AutoCAD называет moveGripPointsAt () функцией, когда пользователь находится в режиме протяжения. Для некоторых объектов, однако, некоторые власти{*захваты*} двигаются объектный скорее чем протяжение этого. Эти власти{*захваты*} включают власти{*захваты*} в текстовые объекты, блоки, midpoints строк, центры кругов, центры эллипсов, и объектов пункта{*точки*}. В этих случаях{*делах*}, moveGripPointsAt () функция вызывает{*называет*} transformBy ().
    ОБРАТИТЕ ВНИМАНИЕ На заданное по умолчанию выполнение AcDbEntity:: moveGripPointsAt () функция должна вызвать transformBy () функция.
    Когда пользователь находится в перемещении власти{*захвата*}, вращать, масштабировать, или отражать режимы, AutoCAD называет transformBy () функцией, описанной в главе 6, “ примитивами. ”
    Если Вы хотите, чтобы  пользователь был способным редактировать ваш объект, используя власти{*захваты*}, вы будете должны перегрузить getGripPoints () и moveGripPointsAt () функции. Объект определяет его пункты{*точки*} власти{*захвата*} и как интерпретировать обеспеченное пользователем смещение.
    Следующая выборка показывает, как заказной AsdkPoly класс осуществляет эти функции. Объект, определенный этим классом имеет пункт{*точку*} власти{*захвата*} в каждой вершине и пункте{*точке*} власти{*захвата*} в его центре. Эти пункты{*точки*} власти{*захвата*} возвращены getGripPoints () функция. Если пользователь выбирает пункт{*точку*} власти{*захвата*}, когда в режиме протяжения власти{*захвата*}, AutoCAD вызывает moveGripPointsAt () функция, проходящая в массиве индексов для выбранных пунктов{*точек*} власти{*захвата*} и трехмерного вектора, определяющего, сколько пользователя переместил устройство управления позицией. Если пользователь выбрал пункт{*точку*} власти{*захвата*} вершины, многоугольник протянут однородно указанным смещением.

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

    Acad::ErrorStatus

    AsdkPoly::getGripPoints(

    AcGePoint3dArray& gripPoints,

    AcDbIntArray& osnapModes,

    AcDbIntArray& geomIds) const

    {

    assertReadEnabled();

    Acad::ErrorStatus es;

    if ((es = getVertices3d(gripPoints)) != Acad::eOk) {

    return es;

    }

    // Remove the duplicate point at the start/end and add

    // center as the last point.

    //

    gripPoints.removeAt(gripPoints.length() - 1);

    AcGePoint3d center;

    getCenter(center);

    gripPoints.append(center);

    return es;

    }

    Acad::ErrorStatus

    AsdkPoly::moveGripPointsAt(

    const AcDbIntArray& indices,

    const AcGeVector3d& offset)

    {

    if (indices.length()== 0 || offset.isZeroLength())

    return Acad::eOk; //that’s easy :-)

    if (mDragDataFlags & kCloneMeForDraggingCalled) {

    mDragDataFlags &= kUseDragCache;

    // We need to make sure that all the poly’s drag data members

    // are in sync with the true data members.

    //

    //mDragCenter = mCenter;

    //mDragStartPoint = mStartPoint;

    } else

    // Only if we’re not dragging do we want to make an undo

    // recording and check if the object’s open for write.

    //

    assertWriteEnabled();

    //if there’s more than one hot vertex or there's one and it is

    //the center then simply transform.

    if (indices.length()>1 || indices[0] == mNumSides)

    return transformBy(AcGeMatrix3d::translation(offset));

    AcGeVector3d off(offset);

    // Calculate the offset vector of the startpoint

    // from the offset vector on a vertex.

    double rotateBy = 2.0 * 3.14159265358979323846 /

    mNumSides * indices[0];

    AcGePoint3d cent;

    getCenter(cent);

    off.transformBy(AcGeMatrix3d::rotation(rotateBy,

    normal(),cent));

    acdbWcs2Ecs(asDblArray(off),asDblArray(off),

    asDblArray(normal()),Adesk::kTrue);

    if (mDragDataFlags & kUseDragCache){

    mDragStartPoint = mStartPoint + AcGeVector2d(off.x,off.y);

    mDragElevation = mElevation + off.z;

    } else{

    mStartPoint = mStartPoint + AcGeVector2d(off.x,off.y);

    mElevation = mElevation + off.z;

    }

    return Acad::eOk;

    }

    Реализация функций OSNAP

    Вы будете должны перегрузить getOsnapPoints () функция, если Вы хотите, чтобы ваш заказной объект поддержал объектные поспешные режимы. AutoCAD вызывает эту функцию, чтобы приобрести уместные поспешные пункты{*точки*} для текущего режима. Если Вы не хотите, чтобы ваш объект поддержал поспешные пункты{*точки*} для специфического режима, Вы можете отфильтровывать поспешные режимы, Вы поддерживаете и возвращаете eOk для другие; AutoCAD запросит пользователя выбирать снова. Если множественные объектные поспешные режимы активны, эта функция называется однажды для каждого объектного поспешного режима.
    ОБРАТИТЕ ВНИМАНИЕ, что  перекрестный объектный поспешный режим обработан по-другому от getOsnapPoints (). Это использует AcDbEntity:: intersectWith (), не getOsnapPoints ().
    Следующие показы, как AsdkPoly класс осуществляет getOsnapPoints () функция:
    Acad::ErrorStatus
    AsdkPoly::getOsnapPoints(
    AcDb::OsnapMode osnapMode,
    int gsSelectionMark,
    const AcGePoint3d& pickPoint,
    const AcGePoint3d& lastPoint,
    const AcGeMatrix3d& viewXform,
    AcGePoint3dArray& snapPoints,
    AcDbIntArray& /*geomIds*/) const
    {
    assertReadEnabled();
    Acad::ErrorStatus es = Acad::eOk;
    if (gsSelectionMark == 0)
    return Acad::eOk;
    if ( osnapMode != AcDb::kOsModeEnd
    && osnapMode != AcDb::kOsModeMid
    && osnapMode != AcDb::kOsModeNear
    && osnapMode != AcDb::kOsModePerp
    && osnapMode != AcDb::kOsModeCen
    && osnapMode != AcDb::kOsModeIns)
    {
    return Acad::eOk;
    }
    // First, check to see if the gsSelection marker is the
    // text geometry. If so, handle center and insertion
    // modes, then return. No need to go into perp, mid, etc.
    //
    AcGePoint3d center;
    getCenter(center);
    if (gsSelectionMark == (mNumSides + 1)) {
    if (osnapMode == AcDb::kOsModeIns)
    snapPoints.append(center);
    else if (osnapMode == AcDb::kOsModeCen)
    snapPoints.append(center);
    return es;
    }
    int startIndex = gsSelectionMark - 1;
    AcGePoint3dArray vertexArray;

    if ((es = getVertices3d(vertexArray)) != Acad::eOk) {

    return es;

    }

    AcGeLineSeg3d lnsg(vertexArray[startIndex],

    vertexArray[startIndex + 1]);

    AcGePoint3d pt;

    AcGeLine3d line, perpLine;

    AcGeVector3d vec;

    AcGeVector3d viewDir(viewXform(Z, 0), viewXform(Z, 1),

    viewXform(Z, 2));

    switch (osnapMode) {

    case AcDb::kOsModeEnd:

    snapPoints.append(vertexArray[startIndex]);

    snapPoints.append(vertexArray[startIndex + 1]);

    break;

    case AcDb::kOsModeMid:

    pt.set(

    ((vertexArray[startIndex])[X]

    + (vertexArray[startIndex + 1])[X]) * 0.5,

    ((vertexArray[startIndex])[Y]

    + (vertexArray[startIndex + 1])[Y]) * 0.5,

    ((vertexArray[startIndex])[Z]

    + (vertexArray[startIndex + 1])[Z]) * 0.5);

    snapPoints.append(pt);

    break;

    case AcDb::kOsModeNear:

    pt = lnsg.projClosestPointTo(pickPoint, viewDir);

    snapPoints.append(pt);

    break;

    case AcDb::kOsModePerp:

    // Create a semi- infinite line and find a point on it.

    //

    vec = vertexArray[startIndex + 1]

    - vertexArray[startIndex];

    vec.normalize();

    line.set(vertexArray[startIndex], vec);

    pt = line.closestPointTo(lastPoint);

    snapPoints.append(pt);

    break;

    case AcDb::kOsModeCen:

    snapPoints.append(center);

    break;

    default:

    return Acad::eOk;

    }

    return es;

    }

    Реализация интерфейса для AutoCAD Дизайн-центра

    Чтобы обеспечивать содержание в Дизайн-центре AutoCAD, необходимо осуществить по крайней мере интерфейс IAcDcContentView. Если приложение предназначено, чтобы участвовать в механизме Средства поиска, то приложение должно поддержать интерфейс IAcDcContentFinder также. Реализация интерфейс IAcDcContentFinder необязательная.
    Как правило, прикладной компонент делал бы следующее:
    §
    В течение инсталляции, это добавляет соответствующие вхождения в системный реестр.
    § Вызывает функции в интерфейсе IAcDcContentBrowser, которые осуществлены структурой Дизайн-центра AutoCAD. Они описаны в следующей таблице:
    Функции интерфейса IAcDcContentBrowser


    Функциональное

    Описание

    AddPaletteItem

    Добавляет элемент в палитре Дизайн-центра AutoCAD.

    AddNavigatorNode

    Необходимый только в случае заказного представления{*вида*}. Добавляет узла в навигаторе Дизайн-центра AutoCAD.

    GetDCFrameWindow

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

    SetItemDescription

    Устанавливает текст описания в области окна описания Дизайн-центра AutoCAD.

    SetPaletteImageList

    Устанавливает маленький / большой список изображения, используемый палитрой в Дизайн-центре AutoCAD.

    SetNavigatorImageList

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

    SetPaletteMultiSelect

    Позволяет опции выбрать множественные довольные{*содержательные*} примитивы в палитре Дизайн-центра AutoCAD.

    InsertPaletteColumn

    Вставляет столбец (подэлемент) для содержательного примитива, обнаруживающегося в палитре.

    DeleteAllPaletteItems

    Удаляет все элементы в палитре Дизайн-центра AutoCAD.

    GetSelectedNavNodeText

    Получает отобранный текст узла навигатора.

    GetCurrentViewMode

    Получает текущий режим представления{*вида*} (рабочий стол, открытые рисунки, и т.д.).

    SetPaletteSubItem

    Устанавливает подъэлемент за элемент в палитре Дизайн-центра AutoCAD.

    SortPaletteItems

    Сортирует элементы в палитре Дизайн-центра AutoCAD.
    <
  • Функции IAcDcContentView связывают с помощью интерфейса в компоненте. Они описаны в следующей таблице:


  • Функции интерфейса IAcDcContentView



    Функция



    Описание



    Initialize



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



    NavigatorNodeClick



    Показывает содержание данного файла в палитре,  вызывая AddPaletteItem

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



    NavigatorMouseUp



    Отображает меню контекста, значимое для данного контейнера.



    PaletteMouseUp



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



    PaletteItemClick



    Кэширует данный отобранный элемент и произвольно устанавливает описание элемента через броузер. Этот метод необязательный.



    RenderPreviewWindow



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



    PaletteItemDblClick



    Показывает содержание контейнера в случае, если нажатый элемент - файл. То, что соответствующее в AutoCAD, если нажатый элемент - содержание, которое компонент отображается.



    PaletteColumnClick



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



    PaletteBeginDrag



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



    ReleaseBrowser



    Выпускает кэшируемый броузер.



    GetLargeImage



    Заставит значок (32x32 предварительного просмотра для данного контейнерного файла обнаруживаться в большом виде значка в Контексте Проекта.



    QueryContextMenu



    Добавляет пункты меню контекста для контейнерного (файла) в палитре к данному меню контекста.



    InvokeCommand



    Вызывает команду при данной команде ID onthe меню контекста, которое компонент обеспечил.


    Реализация Элемента Функции

    Когда Вы определяете новый элемент, функционируют или отменяют существующую функцию, первый запрос, который Вы обычно делаете - assertReadEnabled (), assertWriteEnabled (), или assertNotifyEnabled () чтобы проверить, что объект открытый в правильном состоянии. Из этих трех функций, assertWriteEnabled () наиболее важен. Вы можете использовать эту функцию, чтобы управлять регистрацией отмены модификации, которая встречается в функции элемента. (См. “ Отмена, и Восстановите ” на странице 324.) Даже если Вы не желаете регистрации отмены, существенно{*необходимо*} вызвать assertWriteEnabled (kFalse, kFalse);
    Этот запрос отмечает объект для последующего сохранения. Отказ следовать за этой командой может приводить к разрушенным рисункам.
    Следующая таблица показывает трем возможным состояниям для открытия объекта (чтение, записывать, уведомлять) и указывает, которые утверждают, что запросы преуспевают для каждого состояния. Если объект не открытый в одном из позволенных состояний для утверждающегося функционального запроса, функция не возвращается. AutoCAD выходит, и пользователь запрошен сохранить рисунок.
    Object open for

    Read
    Write
    Notify
    assertReadEnabled()
    returns
    returns
    returns
    assertWriteEnabled()
    aborts
    returns
    aborts
    assertNotifyEnabled()
    returns
    returns
    returns


    Реальные преобразования

    Файл acad.unt определяет разнообразие преобразований между реальными модулями типа миль / километров, Фаренгейта / Цельсия, и так далее. Функция acutCvUnit () берет значение, выраженное в одной системе модулей и возвращает эквивалентное значение в другой системе. Две системы модулей определены строками, которые должны соответствовать одному из определений acad.unt.
    Если модули текущего рисунка технические или архитектурные (футы и дюймы), следующий фрагмент преобразовывает указанное пользователем расстояние в метры.
    ads_real eng_len, metric_len;
    char *prmpt = "Select a distance: ";
    if (acedGetDist(NULL, prmpt, &eng_len) != RTNORM)
    return BAD;
    acutCvUnit(eng_len, "inches", "meters", &metric_len);
    AcutCvUnit () функция не будет преобразовывать несовместимые модули, типа дюймов в годы.

    Редактирование прокси-примитивов

    Степень, к которой прокси-примитивы могут быть отредактированы,  определена родительским приложением. Это определение{*намерение*} сделано, когда класс создан с макрокомандой ACRX_DXF_DEFINE_MEMBERS. Параметр PROXY_FLAGS определяет типы редактирований, которые могут быть сделаны к примитиву, если это становится полномочным. Имеющие силу опции для PROXY_FLAGS, и их связанных значений, перечислены в следующем
    Таблица.
    Полномочные опции флажков


    Опция

     Значение

    KNoOperation

     0

    KEraseAllowed

     0x1

    KTransformAllowed

     0x2

    KColorChangeAllowed

     0x4

    KLayerChangeAllowed

     0x8

    KLinetypeChangeAllowed

     0x10

    KLinetypeScaleChangeAllowed

     0x20

    KVisibilityChangeAllowed

     0x40

    KAllAllowedBits

     0x7F

    Обратите внимание, что kNoOperation не означает ни один из других опций, перечисленных здесь.
    Вы можете логически опции OR PROXY_FLAG, чтобы разрешать комбинацию редактирования операций.
    Поскольку прокси-примитивы только формируют данные ниже уровня базовых классов AcDbEntity, любые изменения, сделанные, чтобы окрасить, уровень, linetype, linetype масштаб, и видимость будет выписан как часть данных прокси-примитива. Твердые преобразования тела (типа перемещения, масштаба, и вращаются) не может применяться, пока родительское приложение не присутствует. Когда преобразование применяется к полномочному, преобразование сделано к графическому метафайлу, и копия матрицы преобразования сохранена в заказной записи в словаре расширений полномочного примитива. Если множественные преобразования выполнены, матрица модифицирована, чтобы отразить совокупное преобразование. Когда заказной примитив возвращен памяти с его родительским приложением, AutoCAD вызывает transformBy() примитива, передает этому данные матрицы преобразования, и удаляет заказную запись хранения данных от словаря расширения. В действительности, преобразование задержано, пока родительское приложение не присутствует, чтобы применить преобразование к заказному примитиву.

    Регистрация классов расширения протокола

    Регистрировать расширение протокола классов с вашим приложением
    1 Инициализируют ваш новый класс родителя расширения протокола и добавляют это к иерархии классов во время выполнения как показано в следующем примере:
    AsdkEntTemperature:: rxInit ();
    аcrxBuildClassHierarchy ();
    Эта функция вызывает,  требованы для любого нового ObjectARX
    класса, как описано в главе 11, при наследовании заказного ObjectARX
    Класса. ”
    2 Создают объект каждого класса расширения протокола и добавляют объекты к соответствующим AcRxClass дескрипторным объектам, использующим addX () функция как показано в следующем примере:
    pDefaultTemp = new AsdkDefaultTemperature();
    pRegionTemp = new AsdkRegionTemperature();
    pCircleTemp = new AsdkCircleTemperature();
     // Добавить объекты расширения протокола к соответствующим объектам AcRxClass.
    //
     AcDbEntity::desc()->addX(AsdkEntTemperature::desc (), pDefaultTemp);
     AcDbRegion::desc()->addX(AsdkEntTemperature::desc (), pRegionTemp);
     AcDbCircle::desc()->addX(AsdkEntTemperature::desc (), pCircleTemp);
    Во время выполнения, ObjectARX создает структуру объекта описателя класса, которая включает основную ObjectARX иерархию классов также как объекты расширения протокола, связанные с ObjectARX объектами описателя класса. Следующее рисунок показывает структуру объекта описателя класса для классов, которые касаются AsdkEntTemperature примера в этой главе:
    Регистрация классов расширения протокола

    Регистрация Приложения

    Прикладные названия сохранены с расширенными данными каждого примитива, который использует их и в APPID таблице. Приложение должно регистрировать имя или называть, это использует. В ObjectARX, это сделано запросом к acdbRegApp (). AcdbRegApp () функция определяет строку, чтобы использовать как прикладное имя. Это возвращает RTNORM, если это может успешно добавлять имя к APPID; иначе, это возвращает RTERROR. Результат RTERROR обычно указывает, что имя - уже в таблице идентификаторов. Это - не фактическое состояние ошибки, а обычно ожидаемое возвращаемое значение, потому что прикладное имя должно быть зарегистрировано только однажды в рисунок.
    Чтобы регистрировать себя, приложение должно сначала проверить, чтобы его имя было уже не в APPID таблице, потому что acdbRegApp () должен быть вызван только однажды в рисунок. Если имя не там, приложение должно регистрировать это; иначе, это может идти вперед и использовать данные.
    Следующий типовой кодовый фрагмент показывает типичному использованию acdbRegApp ().
    #define APPNAME "Local_Operation_App_3-2"
    struct resbuf *rbp;
    static char *local_appname = APPNAME;
    // The static declaration prevents a copy being made of the string
    // every time it’s referenced.
    .
    .
    .
    if ((rbp = acdbTblSearch("APPID", local_appname, 0)) == NULL) {
    if (acdbRegApp(APPNAME) != RTNORM) { // Some other
    // problem
    acutPrintf("Can’t register XDATA for %s.",
    local_appname);
    return BAD;
    }
    } else {
    acutRelRb(rbp);
    }

    Регистрация состояния

    Чтобы делать запись только части государства{*состояния*} объекта, определите kFalse для параметра автоотмены, и затем используйте undoFiler:: writeItem () функция (или другой writexxx () функция) чтобы сохранить{*экономить*} уместную информацию в файле отмены.
    SetNumSides () функция AsdkPoly - типичный пример функции модификации. Поскольку assertWriteEnabled () определяет kFalse для автоотмены, класс принимает ответственность регистрации уместных частей государства{*состояния*} объекта. Сначала, функция модификации должна делать запись объекта описателя класса так, чтобы полученные классы могли проверять{*отмечать*} и позволять этому классу обрабатывать его частичные данные отмены в случае необходимости.
     undoFiler()->writeItem((long)AsdkPoly::desc());
    Тогда функция модификации должна указать тип действия, сопровождаемого данными. В этом примере, тип операции - kSetNumSides, и данные - mNumSides.
    Acad::ErrorStatus
    AsdkPoly::setNumSides(int numSides)
    {
    assertWriteEnabled(Adesk::kFalse, Adesk::kTrue);
    if (numSides<3)
    return Acad::eInvalidInput;
    if (mNumSides == numSides)
    return Acad::eOk;
    // There are situations under which AutoCAD doesn’t
    // want to do undo recording, so it won’t create an
    // undo filer. Check for the existence of the filer
    // before starting to write into it.
    //
    AcDbDwgFiler *pFiler = NULL;
    if ((pFiler = undoFiler()) != NULL) {
    undoFiler()->writeItem((long)AsdkPoly::desc());
    undoFiler()->writeItem((Adesk::Int16)kSetNumSides);
    undoFiler()->writeItem((Adesk::Int32)mNumSides);
    }
    mNumSides = numSides;
    return Acad::eOk;
    }
    Как только объект выполнил авто операцию отмены, которая делает запись ее полных состояний, дополнительных просьб о авто отмене,  игнорируются.

    Режим поля ввода кодируется значениями



    Символ

     Описание

    MODE_ENABLE

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

    MODE_DISABLE

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

    MODE_SETFOCUS

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

    MODE_SETSEL

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

    MODE_FLIP

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

    Имена атрибута и значения пропускают как строки; ваши программы должны разместить пространство для их. Верхний предел на строках, используемых с диалоговыми окнами определен в TILE_STR_LIMIT как 255 плюс один для нулевого признака конца, EOS).

    Режимы Инициализации и Значения

    Инициализация поля ввода включает создание это начальный фокус клавиатуры диалогового окна, отключения или предоставления возможности это, или (если это - окно редактирования или изображение) высвечивание его содержания. Эти операции выполнены ads_mode_tile () вызывает. Вы можете также устанавливать значение поля ввода с ads_set_tile ().
    Следующий код отображает значение по умолчанию, в этом случае фамилия, в окне редактирования и устанавливает поле диалога начальный фокус в то поле:
    strcpy(name_str, "Nugent"); // Default name.
    ads_set_tile(hdlg, "lastname", name_str);
    ads_mode_tile(hdlg, "lastname", MODE_SETFOCUS);
    Следующая инструкция вызывает ads_mode_tile () снова, чтобы высветить содержание окна редактирования так, чтобы пользователь мог немедленно печатать поверх заданного по умолчанию содержания:
    Ads_mode_tile (hdlg, "lastname", MODE_SETSEL);
    На некоторых платформах, устанавливая фокус к окну редактирования автоматически высвечивает это, делая этот дополнительный ненужный шаг.

    Руководящие принципы для Использования Фильтрации Точки ввода и Контроля

    Чтобы гарантировать хорошее выполнение{*работу*}, сохраните следующие руководящие принципы в памяти при кодировании фильтров точки ввода и мониторов:
    §
    Будут внимательным относительно выполнения существенного вычисления изнутри фильтров точки ввода и мониторов.
    § Минимизируют число окон вызова разделов, сделанных от фильтров и мониторов.
    § Воспользуются преимуществом доступной работы, которая уже была сделана в соответствии с AutoCAD, типа списка всех примитивов под курсором объектной привязки и всеми промежуточными вычислениями точки.
    § Убеждаются, что освободил память для строк, которые Вы передаете в additionalTooltipString параметр при создании фильтра точки ввода или монитора.
    ПРИМЕЧАНИЕ, которое рекомендует, чтобы Вы отключили вашу точку, просачивается все контексты выбора примитива. Режим объектной привязки и Автопривязка всегда отключаются в этом контексте.

    Руководящие принципы использования уведомления

    В то время как при использовании уведомлений, твердо придержитесь следующих руководящих принципов. Использование уведомлений, которые нарушают эти руководящие принципы, могло приводить к непредсказуемым результатам для вашего приложения.
    § Не полагаются на последовательность обращения к уведомлениям.
    Вы можете считать  commandWillStart () обстрелянным прежде commandEnded (), и beginInsert () обстрелянный прежде endInsert ().
    Доверие на любые другие последовательности могло бы приводить к проблемам для вашего приложения, если последовательность изменена, когда новые уведомления представлены, или существующие перестроены.
    § Не полагаются на последовательность операций (функция вызывает) между уведомлениями.
    Если Вы связываете ваше приложение с этим уровнем подробности, ваше приложение может терпеть неудачу в будущих выпусках.
    Вместо доверия на последовательности, положитесь на уведомления, чтобы указать состояние системы. Например, когда Вы получаете erased (kTrue) уведомление на объекте A, это означает, что объект A стерт. Если Вы получаете erased() уведомление на сопровождаемом erased() уведомление на B, это означает только, что оба объекта A и B стерты. Система не будет гарантировать, что B будет всегда стираться после A.
    § Не используют никакие функции взаимодействия пользователя в вашей функции повторного вызова уведомления, типа acedCommand (), acedGetPoint (), acedGetKword (), или любого другого acedXXX () функция.
    Подобные интерпретации обращаются к уведомлениям на реакторах базы данных, редактор реакторы, и операционные реакторы.

    SDI Переменная Системы

    ObjectARX
    обеспечивает режим совместимости для единственного интерфейса рисунка (SDI) предыдущих выпусков. Это управляется SDI переменной системы. Возможные значения для SDI
    показываются в следующей таблице:
    SDI
    значения переменной системы

    0              MDI позволяется
    1              SDI режим, установленный пользователем
    2              SDI режим, подразумеваемый загруженными non-MDI-aware приложениями
    3              SDI подразумеваемый режим и пользователем и загруженными non-MDI-aware приложениями
    Знайте следующие ограничения на изменение значения SDI:
    § SDI может только быть установлен в значения 2 или 3 в соответствии с AutoCAD, поскольку приложения загружены и разгружены.
    § Всегда проверяют текущее значение SDI перед созданием изменений. Если текущее значение - 2 или 3, не измените это.
    § Изменяющий SDI к 1 от 0 будет терпеть неудачу, когда AutoCAD имеет больше чем один открытый документ.
    Вся проверка блокировки документа заблокирована, когда AutoCAD выполняется в любом из режимов SDI.
    ОБРАТИТЕ ВНИМАНИЕ На этот режим совместимости, и SDI переменная будет удалена в следующем полном выпуске AutoCAD.

    SDI-ТОЛЬКО Уровень

    Это - основной уровень совместимости и не достаточно для наиболее устойчивых приложений. Этот уровень не будет позволять вашему приложению работать под MDI, но это должно работать без того, чтобы терпеть неудачу под SDI.
    Создавать приложение SDI-Only
    1 Регистрируют ваше приложение как SDI-ТОЛЬКО,  вызывая AcRxDynamicLinker::registerAppNotMDIAware () в kInitAppMsg обработчике acrxEntryPoint ().
    2 Гарантируют, что ваше приложение может брать AcRx:: kUnloadAppMsg немедленно после возвращения от обработки AcRx:: kInitAppMsg. Это произойдет, если ваше приложение не регистрируется как являющийся MDI-ЗНАЮЩИЙ, и AutoCAD уже имеет открытые множественные документы.

    Сеть

    Сеть - эффективный способ сохранить parametrically прямоугольную сетку вершины. Геометрия для сети определена как число строк, число столбцов, и списка вершины, в порядке строки:
    virtual Adesk::Boolean
    AcGiWorldGeometry::mesh(
    const Adesk::UInt32 rows,
    const Adesk::UInt32 columns,
    const AcGePoint3d* pVertexList,
    const AcGiEdgeData* pEdgeData = NULL,
    const AcGiFaceData* pFaceData = NULL,
    const AcGiVertexData* pVertexData = NULL) const = 0;
    Mesh() функция имеет три необязательных параметра для присоединяющихся данных свойства к граням, лицам, или вершине. Для граней в сети, Вы можете прикреплять цвет, уровень, linetype, GS маркер, и свойства видимости. Например, Вы могли использовать AcGiEdgeData:: setColors () чтобы прикрепить различный цвет к каждому краю сети. В цветном списке, сначала перечисляют цвета для всех граней строки, тогда цвета для всех граней столбца. Следующее рисунок показывает упорядочение данных свойства края для типовой сети:
    Сеть
    Следующий типовой код создает сеть и назначает цвета, использующие данные края и данные лица. Это создает сеть " четыре четыре " с голубыми строками и зелеными столбцами.
    Adesk::Boolean
    AsdkMeshSamp::worldDraw(AcGiWorldDraw* pW)
    {
    Adesk::UInt32 i, j, k;
    Adesk::UInt32 numRows = 4;
    Adesk::UInt32 numCols = 4;
    AcGePoint3d *pVerts =
    new AcGePoint3d[numRows * numCols];
    for (k = 0, i = 0; i < numRows; i++) {
    for (j = 0; j < numCols; j++, k++) {
    pVerts[k].x = (double)j;
    pVerts[k].y = (double)i;
    pVerts[k].z = 0.;
    }
    }
    // Construct an array of colors to be applied to each
    // edge of the mesh. In this example, the rows are cyan and
    // the columns are green.
    //
    AcGiEdgeData edgeInfo;
    Adesk::UInt32 numRowEdges = numRows * (numCols - 1);
    Adesk::UInt32 numColEdges = (numRows - 1) * numCols;
    Adesk::UInt32 numEdges = numRowEdges + numColEdges;
    short *pEdgeColorArray = new short[numEdges];
    for (i = 0; i < numEdges; i++) {
    pEdgeColorArray[i] =
    i < numRowEdges ? kCyan : kGreen;
    }
    edgeInfo.setColors(pEdgeColorArray);

    // Make the first face transparent and the rest

    // different colors.

    //

    Adesk::UInt32 numFaces = (numRows - 1)

    * (numCols - 1);

    Adesk::UInt8 *pFaceVisArray =

    new Adesk::UInt8[numFaces];

    short *pFaceColorArray = new short[numFaces];

    AcGiFaceData faceInfo;

    faceInfo.setVisibility(pFaceVisArray);

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

    pFaceVisArray[i] =

    i ? kAcGiVisible : kAcGiInvisible;

    pFaceColorArray[i] = (short)(i + 1);

    }

    faceInfo.setColors(pFaceColorArray);

    // If the fill type is kAcGiFillAlways, then a shell,

    // mesh, or polygon will be interpreted as faces;

    // otherwise, they will be interpreted as edges.

    //

    // Output mesh as faces.

    //

    pW->subEntityTraits().setFillType(kAcGiFillAlways);

    pW->geometry().mesh(numRows, numCols, pVerts, NULL, &faceInfo);

    // Output mesh as edges over the faces.

    //

    pW->subEntityTraits().setFillType(kAcGiFillNever);

    pW->geometry().mesh(numRows, numCols, pVerts, &edgeInfo);

    delete [] pVerts;

    delete [] pEdgeColorArray;

    delete [] pFaceColorArray;

    delete [] pFaceVisArray;

    return Adesk::kTrue;

    }

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

    Сеть

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

    SetAttributes Функция

    AcGi выполнение вызывает setAttributes() функцией на drawable, чтобы получить генерала, выполняющего атрибуты, которые нужно использовать для геометрии объекта, типа цвета, уровня, и linetype. Этот запрос сделан до запроса worldDraw() функции объекта, и AcGi
    использует возвращаемое значение, чтобы решить, как обработать наиболее эффективно объект позже.
    Обычно Вы не будете должны перегрузить setAttributes () функция, но если Вы делаете так, Вы должны вызвать выполнение базового класса сначала и возвращать те же самые флажки в возвращаемом значении. Единственное чередование, которое может быть сделано, должно добавить дополнительные флажки к возвращаемому значению. Для подробной информации относительно флажков возвращения, см. AcGiDrawable:: setAttributes () в ObjectARX Ссылке.
    Заданное по умолчанию выполнение AcDbEntity:: setAttributes () основывает цвет, уровень, linetype, lineweight и графический стиль, используя текущие свойства примитива, и возвращаемое значение включает флажок kDrawableIsEntity.

    Шаблоны ATL

    Если Вы используете ATL наряду с ATL-ОСНОВАННЫМИ шаблонами из AutoCAD, чтобы создать ваши объекты Automation, все интерфейсы, перечисленные выше будут осуществлены автоматически. Вы можете концентрироваться на определенных свойствах и методах для вашего AcDbObject-полученного класса; все остальное осуществлено или Autodesk или Microsoft.
    Autodesk обеспечивает следующие ATL-ОСНОВАННЫЕ шаблоны:
    ATL-ОСНОВАННЫЕ шаблоны (объявлены в axtempl.h)

    Template
    Implements
    CProxy_AcadObjectEvents
    IAcadObjectEvents, IConnectionPoint
    IacadBaseObjectImpl
    IAcadBaseObject, IConnectionPointContainer
    IretrieveApplicationImpl
    IRetrieveApplication
    IacadObjectDispatchImpl
    IAcadObject, IDispatch
    IacadEntityDispatchImpl
    IAcadEntity

    Изменяя образование из ATL IDispatchImpl шаблон к IACADENTITYDISPATCHIMPL или IACADOBJECTDISPATCHIMPL, Вы будете иметь автоматическое выполнение для всех требуемых интерфейсов. Шаги, требуемые осуществлять автоматизацию охвачены подробно в “ Взаимодействующий с AutoCAD. ”

    SimpleView

    SimpleView - выборка vectortaker. Это осуществляет простого менеджера области просмотра и поставляет AcGixSimpleView. AcGixSimpleView объединяет выполнение AcGiViewport и AcGixVectorTaker в отдельный объект. Это выполнение использует GDI Windows, чтобы отобразить результатов перегенеральных на экране. Полное выполнение SimpleView снабжено в исходной форме. Это может изменяться разработчиками, кто желают определить систему управления вида, которая удовлетворяет потребности их приложения. SimpleView предназначен, чтобы демонстрировать то, что требовано, чтобы управлять размещением области просмотра и работать с AcGix, чтобы формировать полный инструмент средства просмотра и служить как отправная точка для такого выполнения.
    SimpleView клиенты непосредственно связываются с библиотекой release/AcGixSimpleView.lib.
    Источник и соответствующий файл проекта Microsoft Visual C++ снабжены в каталоге samples/AcGixSimpleView.
    AcGixBlockView обеспечивает базовый класс для различных типов представлений, которые нужно управлять SimpleView менеджером. Это позволяет, и SimpleView и WhipView управляться полиморфно тем же самым менеджером.
    Использование мьютексов
    баз данных

    Когда приложение позволяет множественным потокам пробегать код базы данных, конфликты в конечном счете возникнут. Они будут обычно приводить к ошибкам в acdbOpenObject или в вашем коде или во внутренних выполнении API. По этой причине, AcGixSimpleView поддерживает базу данных mutex.
    Всякий раз, когда один из SimpleView потоков должен войти в код базы данных, это пробует получать этот mutex, ожидая, пока это не делает. ViewAcDb использует тот же самый mutex, чтобы обратиться к базе данных. Это предотвращает эти два потока от конфликта в пределах кода базы данных.
    Основная процедура для многопоточного программирования - то, что всякий раз, когда Вы запускаете операцию базы данных, назовите getDatabaseMutex () методом в начале операции, и разместите запрос к releaseDatabaseMutex () в конец.
    Они вызывают, должен быть соединен, иначе ваше приложение зависнет. Это означает, что, если Вы имеете инструкцию возвращения где-нибудь в середине вашего кода, удостоверитесь, что Вы имеете запрос к releaseDatabaseMutex () прежде, чем Вы выходите. Вы должны выпустить mutex, как только Вы сделаны, иначе перегенеральный поток будет ждать навсегда.
    Вы можете использовать Mutex класс, включенный в AcGixSimpleViewManager.cpp, чтобы помочь Вам гарантировать, что вызывает,  соединены. AcGixSimpleViewManager класс выставляет три метода для Вас, чтобы получить mutex. DatabaseMutex () метод обеспечивается для прямого доступа к mutex. Получить и методы выпуска обеспечиваются для удобства. Методы –
    void getDatabaseMutex()
    void releaseDatabaseMutex()
    HANDLE databaseMutex()

    Символы AutoLISP

    Функции
    acedGetSym () и acedPutSym () позволяют
    ObjectARX-приложениям осматривать и изменять{*заменять*} значение переменных
    AutoLISP.
    В первом примере, пользователь вводит следующие выражения AutoLISP:
    Command: (setq testboole t)
    T
    Command: (setq teststr “HELLO, WORLD”)
    “HELLO, WORLD”
    Command: (setq sset1 (ssget))

    Тогда следующий типовой код показывает, как acedGetSym() отыскивает новые значения символов.
    struct resbuf *rb;
    int rc;
    long sslen;
    rc = acedGetSym("testboole", &rb);
    if (rc == RTNORM && rb->restype == RTT)
    acutPrintf("TESTBOOLE is TRUE\n");
    acutRelRb(rb);
    rc = acedGetSym("teststr", &rb);
    if (rc == RTNORM && rb->restype == RTSTR)
    acutPrintf("TESTSTR is %s\n", rb->resval.rstring);
    acutRelRb(rb);
    rc = acedGetSym("sset1", &rb);
    if (rc == RTNORM && rb->restype == RTPICKS) {
    rc = acedSSLength(rb->resval.rlname, &sslen);
    acutPrintf("SSET1 contains %lu entities\n", sslen);
    }
    acutRelRb(rb);
    Наоборот, acedPutSym () может создавать или изменять связывание символов AutoLISP, следующим образом:
    ads_point pt1;
    pt1[X] = pt1[Y] = 1.4; pt1[Z] = 10.9923;
    rb = acutBuildList(RTSTR, "GREETINGS", 0);
    rc = acedPutSym("teststr", rb);
    acedPrompt("TESTSTR has been reset\n");
    acutRelRb(rb);
    rb = acutBuildList(RTLB, RTSHORT, -1,
    RTSTR, "The combinations of the world",
    RTSTR, "are unstable by nature.", RTSHORT, 100,
    RT3DPOINT, pt1,
    RTLB, RTSTR, "He jests at scars",
    RTSTR, "that never felt a wound.", RTLE, RTLE, 0);
    rc = acedPutSym("longlist", rb);
    acedPrompt("LONGLIST has been created\n");
    acutRelRb(rb);
    Чтобы устанавливать переменную AutoLISP в ноль, делайте следующее назначение и функциональный запрос:
    rb->restype = RTNIL;
    acedPutSym("var1", rb);
    Пользователи могут отыскивать эти новые значения. (Как показано в примере, ваша программа должна уведомить пользователей относительно любых изменений.)
    TESTSTR has been reset.
    LONGLIST has been created.
    Command: !teststr
    (“GREETINGS”)
    Command: !longlist
    ((-1 “The combinations of the world” “are unstable by nature.” 100 (1.4 1.4
    10.9923) (“He jests at scars” “that never felt a wound.”)))

    Система координат Примитива

    Если Вы определяете ваш собственный примитив, может быть полезно сохранить его геометрические конструкции (точки, углы, и векторы) в терминах его собственной относительной системы координат. Например, дуги устанавливают систему координат, в которой Z ось является перпендикулярной на план дуги. Средняя точка дуги возвращена в мировых координатах, но начало и конечные углы может только интерпретироваться относительно его ECS. В таких случаях, осуществьте getEcs () функция, чтобы возвратить матрицу, которая используется, чтобы преобразовать примитив от его Системы Координаты Примитива до Мировой системы координат. Если примитив не определен в терминах его собственной Системы координат Примитива, то getEcs () функция возвращает единичную матрицу. (Другими словами, любое время getEcs примитива () функция возвращает единичную матрицу, Вы можете предполагать, что  примитив определен в терминах мировых координат.)
    В AutoCAD, плоские примитивы имеют ECS; трехмерные примитивы делают нет. Примитивы AutoCAD, которые могут возвращать матрицу нетождеств для их getEcs () функция:
    § Измерения
    § Текст
    § Круги
    § Дуги
    § 2-ые ломаные линии
    § Блочные вставки
    § Точки
    § Следы
    § Solids
    § Формы
    § определения Атрибута
    § Атрибуты

    Системная переменная DEMANDLOAD

    AutoCAD DEMANDLOAD переменная системы управляет опциями загрузки запроса Приложений ObjectArx. По умолчанию DEMANDLOAD системная переменная установлена (когда AutoCAD установлен) чтобы допустить загрузке запроса приложений на обращении команды или на полномочном обнаружении, когда любая опция определена в системном входе системного реестра для приложения. Установка DEMANDLOAD не затрагивает загрузку запроса на запуске AutoCAD, или по запросу пользователем или приложением, когда любая из этих опций определена в системном системном реестре. (См. “ Создание Дополнительных клавиш AutoCAD и Значений ” на странице 48).
    Законные значения для системной переменной могут использоваться в комбинации.
    Они определены следующим образом:
    0 Отключает загрузку запроса всех Приложений ObjectArx.
    1 Допускает загрузке запроса Приложений ObjectArx после обнаружения полномочных объектов{*целей*}.
    2 Допускает загрузке запроса Приложений ObjectArx на обращение команды.
    3 Допускает загрузке запроса для и полномочных объектов{*целей*} и обращения команды (значение по умолчанию).
    DEMANDLOAD системная переменная позволяет пользователю отключать загрузку запроса всех Приложений ObjectArx, которые имеют системные параметры настройки системного реестра, определяющие загрузку запроса на обращении команды, и полномочном обнаружении. Это не может заставлять приложение быть загруженным запросом, если соответствующие системные параметры настройки системного реестра не существуют.

    Системные Переменные

    Пара функций, acedGetVar () и acedSetVar (), дает возможность ObjectARX-приложениям осматривать и изменить значение переменных системы AutoCAD.
    Эти функции используют строку, чтобы определить имя переменной (или в верхнем регистре или нижнем регистре), и (одиночном) буфере результатов для типа и значения переменной.
    Буфер результатов требуется в этом случае, потому что переменные системы AutoCAD входят в разнообразие типов: целые числа, реальные значения, строки, 2-ые точки, и трехмерные точки.
    Следующий типовой кодовый фрагмент гарантирует, что последующие команды FILLET используют радиус по крайней мере 1.
    struct resbuf rb, rb1;
    acedGetVar("FILLETRAD", &rb);
    rb1.restype = RTREAL;
    rb1.resval.rreal = 1.0;
    if (rb.resval.rreal < 1.0)
    if (acedSetVar("FILLETRAD", &rb1) != RTNORM)
    return BAD; // Setvar failed.
    В этом примере, буфер результатов распределен как динамическая локальная переменная, когда это объявлено в приложении. Приложение должно явно не управлять использованием памяти буфера, поскольку это делает с динамически распределенными буферами.
    Если переменная системы AutoCAD - строковый тип, acedGetVar () распределяет пространство для строки. Приложение ответствено за освобождение этого пространства{*пробела*}. Вы можете делать это,  вызывая функцию стандартной библиотеки для C свободный (), как показано в следующем примере:
    acedGetVar("TEXTSTYLE", &rb);
    if (rb.resval.rstring != NULL)
    // Release memory acquired for string:
    free(rb.resval.rstring);

    Словарь имен объектов

    Словарь имен объектов имеет мягкое монопольное использование ее вхождений. Вхождения не таким образом клонировались wblockClone (). Это - до приложения, чтобы копировать те объекты в случае необходимости.
    В течение команды INSERT, определенные приложением вхождения в словари имен объектов не скопированы. Приложение должно исполнить желательное клонирование в течение beginDeepCloneXlation() стадия, добавляя объектные ID к карте ID и добавляя новый вход адресата в словарь.
    Для подробной информации относительно beginDeepCloneXlation(), см. “ Редактор Функции Уведомления Реактора ” на странице 504.
    В течение команды WBLOCK, все ID в первоначальной словари имен объектов принесены к словари имен объектов адресата, но объекты указали,  автоматически не скопированы. Если объект, на который ID указывает,  не клонировался приложением, ID удален из словаря адресата в течение endDeepClone () трансляция. Снова, приложение должно клонировать объекты в течение beginDeepCloneXlation и добавлять ID к карте ID. Не требоваться добавить новый ID к словари имен объектов адресата, потому что эта задача была выполнена автоматически.
    Следующий пример показывает, как Вы могли бы записывать AcEditorReactor:: beginDeepCloneXlation () функция для определяемого пользователем словаря объектов, который помещен в словарь имен объектов. Пример относится только к kDcWblock и kDcInsert контекстам.
    // Этот пример демонстрирует способ обработать объекты в словари имен объектов для WBLOCK
    и INSERT.
    // Наш объект - AcDbDictionary, который назван "AsdkDictionary" в названном словаре объектов, содержащим
    // наши заказные объекты.
    //
    const char *kpDictionary = "AsdkDictionary";
    // AsdkNODEdReactor is derived from AcEditorReactor.
    //
    void
    AsdkNODEdReactor::beginDeepCloneXlation( AcDbIdMapping& idMap, Acad::ErrorStatus* pRetStat)
    {
    Acad::ErrorStatus es;
    AcDbObjectId dictId;
    if ( idMap.deepCloneContext() != AcDb::kDcWblock && idMap.deepCloneContext() != AcDb::kDcInsert)

    return;

    // Get the "from" and "to" databases.

    //

    AcDbDatabase *pFrom, *pTo;

    idMap.origDb(pFrom);

    idMap.destDb(pTo);

    // See if the "from" database has our dictionary, and

    // open it. If it doesn’ t have one, we are done.

    //

    AcDbDictionary *pSrcNamedObjDict;

    pFrom->getNamedObjectsDictionary(pSrcNamedObjDict, AcDb::kForRead);

    es = pSrcNamedObjDict->getAt(kpDictionary, dictId);

    pSrcNamedObjDict->close();

    if (es == Acad::eKeyNotFound)

    return;

    AcDbDictionary *pSrcDict;

    acdbOpenObject(pSrcDict, dictId, AcDb::kForRead);

    AcDbObject *pClone;

    switch (idMap.deepCloneContext()) {

    case AcDb::kDcWblock:

    // WBLOCK clones all or part of a drawing into a

    // newly created drawing. This means that the

    // named object dictionary is always cloned, and

    // its AcDbObjectIds are in flux. Therefore, you

    // cannot use getAt() or setAt() on the dictionary

    // in the new database. This is because the

    // cloned dictionary references all refer to the

    // original objects. During deep clone translation,

    // all cloned entries will be translated to the

    // new objects, and entries not cloned will be

    // "removed" by getting "translated" to NULL.

    //

    // The cloning of entries in our own dictionary are

    // not handled here. If all are to be cloned, then

    // call setTreatElementsAsHard(Adesk::kTrue) on the

    // dictionary. Otherwise, only those entries that

    // are referred to by hard references in other

    // wblocked objects will have been cloned via

    // those references.

    // In this example, we will always write out all of

    // the records. Since TreatElementsAsHard is not

    // currently persistent, we reset it here each time.

    //

    pSrcDict->upgradeOpen();

    pSrcDict->setTreatElementsAsHard(Adesk::kTrue);

    pClone = NULL;

    pSrcDict->wblockClone(pTo, pClone, idMap,

    Adesk::kFalse);

    if (pClone != NULL)

    pClone->close();

    break;

    case AcDb::kDcInsert:

    // In INSERT, an entire drawing is cloned, and

    // "merged" into a pre-existing drawing. This


    // means that the destination drawing may already

    // have our dictionary, in which case we have to

    // merge our entries into the destination

    // dictionary. First we must find out if

    // the destination named objects dictionary contains

    // our dictionary.

    //

    AcDbDictionary *pDestNamedDict;

    pTo->getNamedObjectsDictionary(pDestNamedDict, AcDb::kForWrite);

    // Since INSERT does not clone the destination

    // named object dictionary, we can use getAt()

    // on it.

    //

    es = pDestNamedDict->getAt(kpDictionary, dictId);

    // If our dictionary does not yet exist in the

    // named object dictionary, which is not itself

    // cloned, we have to both clone and add our

    // dictionary to it. Since dictionary entries are

    // ownership references, all of our entries will

    // also be cloned at this point, so we are done.

    //

    if (es == Acad::eKeyNotFound) {

    pClone = NULL;

    pSrcDict->deepClone(pDestNamedDict, pClone, idMap);

    // Unless we have overridden the deepClone()

    // of our dictionary, we should expect it to

    // always be cloned here.

    //

    if (pClone == NULL) {

    *pRetStat = Acad::eNullObjectId;

    break;

    }

    pDestNamedDict->setAt(kpDictionary, pClone, dictId);

    pDestNamedDict->close();

    pClone->close();

    break;

    }

    pDestNamedDict->close();

    // Our dictionary already exists in the destination

    // database, so now we must "merge" the entries

    // into it. Since we have not cloned our

    // destination dictionary, its object IDs are not in

    // flux, and we can use getAt() and setAt() on it.

    //

    AcDbDictionary *pDestDict;

    acdbOpenObject(pDestDict, dictId, AcDb::kForWrite);

    AcDbObject *pObj, *pObjClone;

    AcDbDictionaryIterator* pIter;

    pIter = pSrcDict->newIterator();

    for (; !pIter->done(); pIter->next()) {

    const char *pName = pIter->name();

    pIter->getObject(pObj, AcDb::kForRead);

    // If the dictionary contains any references

    // and/or other objects have references to it,

    // you must either use deepClone() or put the

    // ID pairs into the ID map here, so that they


    // will be in the map for translation.

    //

    pObjClone = NULL;

    pObj->deepClone(pDestDict, pObjClone, idMap);

    // INSERT usually uses a method of cloning

    // called CheapClone, where it "moves" objects

    // into the destination database instead of

    // actually cloning them. When this happens,

    // pObj and pObjClone are pointers to the

    // same object. We only want to close pObj

    // here if it really is a different object.

    //

    if (pObj != pObjClone)

    pObj->close();

    if (pObjClone == NULL)

    continue;

    // If the name already exists in our

    // destination dictionary, it must be changed

    // to something unique. In this example, the

    // name is changed to an anonymous entry.

    // The setAt() method will automatically append

    // a unique identifier to each name beginning

    // with "*", for example: "*S04".

    //

    if ( pDestDict->getAt(pName, dictId) == Acad::eKeyNotFound)

    pDestDict->setAt(pName, pObjClone, dictId);

    else

    pDestDict->setAt("*S", pObjClone, dictId);

    pObjClone->close();

    }

    delete pIter;

    pDestDict->close();

    break;

    default:

    break;

    }

    pSrcDict->close();

    }

    Словарь Расширения

    Каждый объект может иметь словарь расширения{*продления*}, который может содержать произвольный набор объектов AcDbObject. При использовании этого механизма, несколько приложений могут прикреплять данные к тому же самому объекту. Словарь расширения{*продления*} требует более верхний чем xdata, но это также обеспечивает более гибкий механизм более высокой способностью{*вместимостью*} для добавляющихся данных.
    Для примера использования словаря расширения{*продления*}, чтобы прикрепить произвольную строку к любому AcDbObject, см. программу edinvent в каталоге выборок.
    Следующий пример показывает instantiating xrecord и добавление этого к словарю расширения{*продления*} в названном объектном словаре:
    void
    createXrecord()
    {
    AcDbXrecord *pXrec = new AcDbXrecord;
    AcDbObject *pObj;
    AcDbObjectId dictObjId, xrecObjId;
    AcDbDictionary* pDict;
    pObj = selectObject(AcDb::kForWrite);
    if (pObj == NULL) {
    return;
    }
    // Try to create an extension dictionary for this
    // object. If the extension dictionary already exists,
    // this will be a no-op.
    //
    pObj->createExtensionDictionary();
    // Get the object ID of the extension dictionary for the
    // selected object.
    //
    dictObjId = pObj->extensionDictionary();
    pObj->close();
    // Open the extension dictionary and add the new
    // xrecord to it.
    //
    acdbOpenObject(pDict, dictObjId, AcDb::kForWrite);
    pDict->setAt("ASDK_XREC1", pXrec, xrecObjId);
    pDict->close();
    // Create a resbuf list to add to the xrecord.
    //
    struct resbuf* head;
    ads_point testpt = {1.0, 2.0, 0.0};
    head = acutBuildList(AcDb::kDxfText,
    "This is a test Xrecord list",
    AcDb::kDxfXCoord, testpt,
    AcDb::kDxfReal, 3.14159,
    AcDb::kDxfAngle, 3.14159,
    AcDb::kDxfColor, 1,
    AcDb::kDxfInt16, 180,
    0);
    // Add the data list to the xrecord. Notice that this
    // member function takes a reference to a resbuf NOT a
    // pointer to a resbuf, so you must dereference the
    // pointer before sending it.
    //
    pXrec->setFromRbChain(*head);

    pXrec->close();

    acutRelRb(head);

    }

    // The listXrecord() function gets the xrecord associated with the

    // key "ASDK_XREC1" and lists out its contents by passing the resbuf

    // list to the function printList().

    //

    void

    listXrecord()

    {

    AcDbObject *pObj;

    AcDbXrecord *pXrec;

    AcDbObjectId dictObjId;

    AcDbDictionary *pDict;

    pObj = selectObject(AcDb::kForRead);

    if (pObj == NULL) {

    return;

    }

    // Get the object ID of the object’s extension dictionary.

    //

    dictObjId = pObj->extensionDictionary();

    pObj->close();

    // Open the extension dictionary and get the xrecord

    // associated with the key ASDK_XREC1.

    //

    acdbOpenObject(pDict, dictObjId, AcDb::kForRead);

    pDict->getAt("ASDK_XREC1", (AcDbObject*&)pXrec,

    AcDb::kForRead);

    pDict->close();

    // Get the xrecord’s data list and then close the xrecord.

    //

    struct resbuf *pRbList;

    pXrec->rbChain(&pRbList);

    pXrec->close();

    printList(pRbList);

    acutRelRb(pRbList);

    }



    Глобальный Функциональный Пример

    Следующий пример использует глобальные функции ObjectARX, чтобы создать xrecord и прибавлять это к словарю, связанному с клавишей ASDK_REC{*ключом*}.

    int

    createXrecord()

    {

    struct resbuf *pXrec, *pEnt, *pDict, *pTemp, *pTemp2;

    ads_point dummy, testpt = {1.0, 2.0, 0.0};

    ads_name xrecname, ename, extDict = {0L, 0L};

    // Have the user select an entity. Then get its data.

    //

    if (acedEntSel("\nselect entity: ", ename, dummy) != RTNORM)

    {

    acutPrintf("\nNothing selected");

    acedRetVoid();

    return RTNORM;

    }

    pEnt = acdbEntGet(ename);

    // Now check to see if the entity already has an

    // extension dictionary.

    //

    for (pTemp = pEnt; pTemp->rbnext != NULL; pTemp = pTemp->rbnext)

    {

    if (pTemp->restype == 102) {

    if (!strcmp("{ACAD_XDICTIONARY", pTemp->resval.rstring))

    {

    ads_name_set(pTemp->rbnext->resval.rlname, extDict);

    break;

    }

    }

    }

    // If no extension dictionary exists, add one.

    //

    if (extDict[0] == 0L) {


    pDict = acutBuildList(RTDXF0, "DICTIONARY", 100,

    "AcDbDictionary", 0);

    acdbEntMakeX(pDict, extDict);

    acutRelRb(pDict);

    pDict = acutBuildList(102, "{ACAD_XDICTIONARY", 360,

    extDict, 102, "}", 0);

    for (pTemp = pEnt; pTemp->rbnext->restype != 100; pTemp = pTemp->rbnext)

    { ; }

    for (pTemp2 = pDict; pTemp2->rbnext != NULL; pTemp2 = pTemp2->rbnext)

    { ; }

    pTemp2->rbnext = pTemp->rbnext;

    pTemp->rbnext = pDict;

    acdbEntMod(pEnt);

    acutRelRb(pEnt);

    }

    // At this point the entity has an extension dictionary.

    // Create a resbuf list of the xrecord’s entity information

    // and data.

    //

    pXrec = acutBuildList(RTDXF0, "XRECORD",

    100, "AcDbXrecord",

    1, "This is a test Xrecord list", //AcDb::kDxfText

    10, testpt, //AcDb::kDxfXCoord

    40, 3.14159, //AcDb::kDxfReal

    50, 3.14159, //AcDb::kDxfAngle

    60, 1, //AcDb::kDxfColor

    70, 180, //AcDb::kDxfInt16

    0);

    // Create the xrecord with no owner set. The xrecord’s

    // new entity name will be placed into the xrecname

    // argument.

    //

    acdbEntMakeX (pXrec, xrecname);

    acutRelRb (pXrec);

    // Set the xrecord’s owner to the extension dictionary

    //

    acdbDictAdd(extDict, "ASDK_XRECADS", xrecname);

    acedRetVoid();

    return RTNORM;

    }

    // Accesses the xrecord associated with the key ASDK_XRECADS in

    // the extension dictionary of a user-selected entity. Then

    // list out the contents of this xrecord using the printList

    // function.

    //

    int

    listXrecord()

    {

    struct resbuf *pXrec, *pEnt, *pTemp;

    ads_point dummy;

    ads_name ename, extDict = {0L, 0L};

    // Have the user select an entity; then get its data.

    //

    if (acedEntSel("\nselect entity: ", ename, dummy) != RTNORM) {

    acutPrintf("\nNothing selected");

    acedRetVoid();

    return RTNORM;

    }

    pEnt = acdbEntGet(ename);

    // Get the entity name of the extension dictionary.

    //

    for (pTemp = pEnt;pTemp->rbnext != NULL;pTemp = pTemp->rbnext) {

    if (pTemp->restype == 102) {

    if (!strcmp("{ACAD_XDICTIONARY", pTemp->resval.rstring)){

    ads_name_set(pTemp->rbnext->resval.rlname, extDict);

    break;

    }

    }

    }

    if (extDict[0] == 0L) {

    acutPrintf("\nNo extension dictionary present.");

    return RTNORM;

    }

    pXrec = acdbDictSearch(extDict, "ASDK_XRECADS", 0);

    if(pXrec) {

    printList(pXrec);

    acutRelRb(pXrec);

    }

    acedRetVoid();

    return RTNORM;

    }

    Словари

    Чтобы создавать новый словарь, Вы должны создать образец AcDbDictionary, добавлять это к базе данных, и регистрировать это с ее объектом владельца. Используйте setAt () функция AcDbDictionary, чтобы добавить объекты к словарю и базе данных.
    Сигнатура этой функции
    Acad::ErrorStatus
    AcDbDictionary::setAt(const char* pSrchKey,
    AcDbObject* pNewValue,
    AcDbObjectId& retObjId);
    SetAt () функция добавляет новый вход, указанный newValue к словарю. Если вход уже существует, это заменено новым значением. Имя объекта определено srchKey. Объект ID входа возвращен в retObjId.
    Когда Вы добавляете вход в словарь, словарь автоматически присоединяет{*придает*} реактор к входу. Если объект стерт, словарь уведомлен и удаляет это из словаря.

    Сложные примитивы

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

    Сложный примитив (ломаная линия или блок) должен быть создан множителем, вызывает к acdbEntMake(), используя отдельный запрос каждый подпримитив. Когда acdbEntMake() сначала получает начальный компонент для сложного примитива, это создает временный файл,  чтобы собрать данные определения (и расширенные данные, если есть). Каждый последующий acdbEntMake() запрос добавляет новый подпримитив к файлу. Когда определение сложного примитива закончено (то есть когда acdbEntMake() получает соответствующий Seqend или Endblk подпримитив), примитив проверен для последовательности, и если допустимо, это добавлено к рисунку.
    Файл удален, когда сложный примитив закончен или когда его создание отменено.
    Следующий пример содержит пять, вызывает acdbEntMake () которые создают одиночный сложный примитив, ломаную линию. Ломаная линия имеет linetype ПОДЧЕРКНУТОГО ШТРИХОВОЙ ЛИНИЕЙ и цвет СИНИХ. Это имеет три вершина, расположенные в (1,1,0) координатах, (4,6,0), и (3,2,0). Все другие необязательные данные определения принимают значения по умолчанию.
    int status;
    struct resbuf *entlist, result;
    ads_point newpt;
    entlist = acutBuildList(
    RTDXF0, "POLYLINE",// Entity type
    62, 5, // Color (blue)
    6, "dashed",// Linetype
    66, 1, // Vertices follow.
    0);
    if (entlist == NULL) {
    acdbFail("Unable to create result buffer list\n");
    return BAD;
    }
    status = acdbEntMake(entlist);
    acutRelRb(entlist); // Release acdbEntMake() buffer.
    if (status != RTNORM) {
    acutPrintf ("%d",status);
    acedGetVar ("ERRNO", &result);
    acutPrintf ("ERRNO == %d, result.resval.rint);
    acdbFail("Unable to start polyline\n");
    return BAD;
    }
    newpt[X] = 1.0;
    newpt[Y] = 1.0;
    newpt[Z] = 0.0; // The polyline is planar
    entlist = acutBuildList(
    RTDXF0, "VERTEX", // Entity type
    62, 5, // Color (blue)
    6, "dashed", // Linetype
    10, newpt, // Start point
    0);
    if (entlist == NULL) {
    acdbFail("Unable to create result buffer list\n");

    События контекста ввода

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

    Тип
     Описание
    Статический
     Введенный, когда beginQuiescentState () повторный вызов сделан, и выходится, когда endQuiescentState () повторный вызов сделан в результате команды AutoCAD, функции AutoLISP, или инициализируемой функции ввода ActiveX. Это должно быть единственное состояние в стеке для документа, когда это введено; это не может быть помещено в стек на вершине другого состояния. CMDACT переменная системы нулевая когда в этом состоянии.
    Геометрический объект, Точка
     Введенный, если beginGetPoint () повторный вызов сделан без уже нахождения в Геометрическом объекте, Переходном процессе Неточки, Отбор Переходного процесса, или Перетаскивать состояние Последовательности. Всякий раз, когда это состояние введено, возвращенная точка - окончательная цель, не промежуточное значение. Фильтры ввода точки  и мониторы запрашивают все события в этом состоянии.
    Геометрический объект, Неточка
     Введенный от Геометрического объекта, Ненаправляет Переходный процесс, когда beginGetPoint () повторный вызов сделан. От этого состояния, другой запрос направлять средства ввода, располагающие в стеке новое состояние. Любая точка - промежуточное значение и может быть перегружена непосредственно напечатанным значением. Из этого состояния выходят, когда любой из endGetAngle (), endGetDistance
    (), endGetOrientation
    (), endGetCorner
    (), или endGetScaleFactor
    () повторные вызовы сделан. Фильтры ввода точки и мониторы запрашивают все события в этом состоянии.
    Выбирая
     Введенный от Отбор, Переходный процесс, когда beginGetPoint
    () повторный вызов сделан. Фильтры ввода точки и мониторы запрашивают все события в этом состоянии.
    Негеометрический объект, Невыбирая
     Введенный, когда любой из beginGetString
    (), beginGetKeyword
    (), beginGetInteger
    (), beginGetColor
    (), или beginGetReal
    () повторные вызовы сделаны. Эти контексты непосредственно голосуют для ввода и не исполняют объектную привязку, Автопривязку, или фильтрацию точки входа, даже при том, что курсор активен, когда интерактивный трэкинг цифрового преобразователя выполнен. Принудительный выбор примитива нужно позволить для мониторов ввода точки получить повторные вызовы от этого состояния. Фильтры ввода точки не вызваны от этого состояния.
    Перетащите Последовательность
     Введенный, когда beginDragSequence () повторный вызов сделан, и выходится, когда endDragsequence () повторный вызов сделан. Вложенный вызывает к beginGetPoint
    (), beginGetAngle
    (), и beginGetDistance
    () сделаны в промежуточном режиме, так что никакой государственный переход не сделан. Фильтры ввода точки и мониторы запрашивают все события в этом состоянии.
    Освободите Переходный процесс
    Из  наиболее удаленного входного состояния выходят, и новый собирается быть введенным.
    Геометрический объект, Неточка Переходный процесс
    Введенный, когда beginGetAngle(), beginGetDistance(), beginGetOrientation(), beginGetCorner(), или beginGetScaleFactor() повторные вызовы сделаны, кроме того, когда уже в Перетаскивают состояние Последовательности. Это означает, что вложил подсказки,  возвратится, немедленно и изменение состояния сделано. Ввод этого состояния подразумевает добавление входного контекста к состоянию ввода стеку для документа. Это состояние всегда переходы к Геометрическому объекту, Неточка с beginGetPoint
    () повторный вызов.
    Отбор Переходного процесса
    Введенный, когда любой из beginEntsel
    (), beginNentsel
    (), или beginSSGet
    () повторные вызовы сделаны. Будет или в непосредственном{*немедленном*} выборе режима, заявляют, или будет переход в состояние Отбора с beginGetPoint
    () повторный вызов.
    Перетащите Последовательность,Вложенную Действие, Переходный процесс
    Введенным от Перетаскивают Последовательность, когда AcEditorReactor::commandWillBegin() или AcEditorReactor::LispWillStart() повторные вызовы сделаны. Они приостанавливают Перетащенную Последовательность и располагают в стеке новое состояние ввода на вершине этого. От этого состояния, это возможно к переходу к любому другому состоянию ввода. Это помещенное в стек состояние закончится, когда балансирование AcEditorReactor
    повторный вызов сделано, и состояние под высшим состоянием - Перетаскивают Последовательность.
    <
    Когда ваше приложение загружено, Вы можете сделать запрос значения переменной системы CMDACT, чтобы выяснить, который команды являются активными. События контекста ввода могут использоваться, чтобы обратить внимание на переходы между состояниями ввода.
    Пример событий контекста ввода
    Следующий пример создает простой реактор контекста, который отвечает на разнообразие событий контекста ввода:
    #include
    #include
    #include
    #include
    #include
    #include
    // The input context reactor class.
    //
    class MyContextReactor : public AcEdInputContextReactor
    {
    public:
    void
    beginGetPoint(
    const AcGePoint3d* pointIn,
    const char* promptString,
    int initGetFlags,
    const char* pKeywords);
    void
    endGetPoint(
    Acad::PromptStatus returnStatus,
    const AcGePoint3d& pointOut,
    const char*& pKeyword);
    void
    beginGetOrientation(
    const AcGePoint3d* pointIn,
    const char* promptString,
    int initGetFlags,
    const char* pKeywords);
    void
    endGetOrientation(
    Acad::PromptStatus returnStatus,
    double& angle,
    const char*& pKeyword);
    void
    beginGetCorner(
    const AcGePoint3d* firstCorner,
    const char* promptString,
    int initGetFlags,
    const char* pKeywords);
    void
    endGetCorner(
    Acad::PromptStatus returnStatus,
    AcGePoint3d& secondCorner,
    const char*& pKeyword);
    void
    beginSSGet(
    const char* pPrompt,
    int initGetFlags,
    const char* pKeywords,
    const char* pSSControls,
    const AcArray& points,
    const resbuf* entMask);
    void
    endSSGet(
    Acad::PromptStatus returnStatus,
    const AcArray& ss);
    };
    void
    MyContextReactor::beginGetPoint(
    const AcGePoint3d* pointIn,
    const char* promptString,
    int initGetFlags,
    const char* pKeywords)
    {
    acutPrintf("beginGetPoint: pointIn = %.2f,%.2f,%.2f\n",
    (*pointIn)[0], (*pointIn)[1], (*pointIn)[2]);
    if (NULL != promptString)
    acutPrintf("%s", promptString);


    acutPrintf("initGetFlags: %d\n", initGetFlags);
    if (NULL != pKeywords)
    acutPrintf("Keywords: %s\n", pKeywords);
    }
    void
    MyContextReactor::endGetPoint(
    Acad::PromptStatus returnStatus,
    const AcGePoint3d& pointOut,
    const char*& pKeyword)
    {
    acutPrintf("endGetPoint: %d\n", returnStatus);
    acutPrintf("%.2f,%.2f,%.2f\n", pointOut[0], pointOut[1],
    pointOut[2]);
    if (NULL != pKeyword)
    acutPrintf("Keyword: %s\n", pKeyword);
    }
    void
    MyContextReactor::beginGetOrientation(
    const AcGePoint3d* pointIn,
    const char* promptString,
    int initGetFlags,
    const char* pKeywords)
    {
    acutPrintf("beginGetOrientation: %.2f, %.2f, %.2f\n",
    (*pointIn)[0], (*pointIn)[1], (*pointIn)[2]);
    }
    void
    MyContextReactor::endGetOrientation(
    Acad::PromptStatus returnStatus,
    double& angle,
    const char*& pKeyword)
    {
    acutPrintf("endGetOrientation: %.2f\n", angle);
    }
    void
    MyContextReactor::beginGetCorner(
    const AcGePoint3d* firstCorner,
    const char* promptString,
    int initGetFlags,
    const char* pKeywords)
    {
    if (NULL != firstCorner)
    {
    acutPrintf(
    "beginGetCorner: %.2f, %.2f, %.2f\n",
    (*firstCorner)[0],
    (*firstCorner)[1],
    (*firstCorner)[2]);
    }
    }
    void
    MyContextReactor::endGetCorner(
    Acad::PromptStatus returnStatus,
    AcGePoint3d& secondCorner,
    const char*& pKeyword)
    {
    acutPrintf("endGetCorner\n");
    }
    void
    MyContextReactor::beginSSGet(
    const char* pPrompt,
    int initGetFlags,
    const char* pKeywords,
    const char* pSSControls,
    const AcArray& points,
    const resbuf* entMask)
    {
    acutPrintf("beginSSGet:%s\n", NULL != pPrompt ? pPrompt : "");
    for (int i = 0; i < points.length(); i++)
    acutPrintf("%d: %.2f, %.2f, %.2f\n", i, points[i][X],
    points[i][Y], points[i][Z]);
    }
    void
    MyContextReactor::endSSGet(
    Acad::PromptStatus returnStatus,
    const AcArray& ss)


    {
    acutPrintf("endSSGet\n");
    for (int i = 0; i < ss.length(); i++)
    acutPrintf("Entity %d: <%x>\n", i, ss[i].asOldId());
    }
    // My context reactor object
    MyContextReactor my_icr;
    extern "C" __declspec(dllexport) AcRx::AppRetCode
    acrxEntryPoint(
    AcRx::AppMsgCode msg,
    void *p)
    {
    switch (msg)
    {
    case AcRx::kInitAppMsg:
    acrxUnlockApplication(p);
    acrxRegisterAppMDIAware(p);
    break;
    case AcRx::kLoadDwgMsg:
    // Attach a context reactor to the current document.
    //
    curDoc()->inputPointManager()->
    addInputContextReactor(&my_icr);
    break;
    case AcRx::kUnloadAppMsg:
    // Warning! This sample attaches a context reactor,
    // but it never detaches it. A real-life application
    // will need to monitor to which document it attached
    // the reactor, and will need to detach it.
    //
    break;
    }
    return AcRx::kRetOK;
    }

    События уведомления документа

    ObjectARX-приложения должны осуществить менеджера документа реактор, чтобы получить уведомление относительно изменений состояния документа, если любое из следующих условий применяется:
  • Они должны управлять состоянием "в документ".

  • Они должны быть уведомлены всякий раз, когда документ или его база(ы) данных собираются изменяться или изменения уже сделаны.

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

  • AcApDocManReactor делает повторные вызовы, когда изменения в состоянии документа имеют место, типа открытия, закрытия, активации, дезактивации и изменения состояние блокировки документов.

    Соединение AcDbTextStyleTableRecord с AcGiTextStyle

    Имеются несколько глобальных сервисных функций, доступные, чтобы копировать текстовые данные стиля от AcDbTextStyleTableRecord до AcGiTextStyle, и наоборот.
    Следующие функции используют объект ID AcDbTextStyleTableRecord и ссылки к AcGiTextStyle, чтобы идентифицировать эти два вовлеченные объекта:
    Acad::ErrorStatus
    fromAcDbTextStyle(
    AcGiTextStyle& textStyle,
    const AcDbObjectId& AcDbStyleId);
    Acad::ErrorStatus
    toAcDbTextStyle(
    const AcDbObjectId AcDbStyleId,
    AcGiTextStyle& textStyle);
    Следующие функции используют имена AcDbTextStyleTableRecord и AcGiTextStyle:
    Acad::ErrorStatus
    fromAcDbTextStyle(
    AcGiTextStyle& textStyle,
    const char* AcDbStyleName);
    Acad::ErrorStatus
    toAcDbTextStyle(
    AcGiTextStyle& textStyle);
    Acad::ErrorStatus
    toAcDbTextStyle(
    AcGiTextStyle& textStyle,
    const char* AcDbStyleName);
    При копировании данных к или от AcDbTextStyleTableRecord, который был определен по имени, имя объекта AcGiTextStyle установлено, чтобы соответствовать имени AcDbTextStyleTableRecord. Если никакая запись не найдена при копировании к AcDbTextStyleTableRecord, указанному по имени, то каждый создан.
    При копировании от AcGiTextStyle до AcDbTextStyleTableRecord и имени AcGiTextStyle используется как имя AcDbTextStyleTableRecord, если AcGiTextStyle не имеет имени, уникальное имя сгенерировано и используется как имя для объектов AcGiTextStyle и AcDbTextStyleTableRecord.
    Следующие функции подобны предыдущим функциям, за исключением того, что они используют параметр AcDbObjectId для objectId AcDbTextStyleTableRecord, в который данные был скопированы.
    Acad::ErrorStatus
    toAcDbTextStyle(
    AcGiTextStyle& textStyle,
    AcDbObjectId& AcDbStyleId);
    Acad::ErrorStatus
    toAcDbTextStyle(
    AcGiTextStyle& textStyle,
    const char* AcDbStyleName,
    AcDbObjectId& AcDbStyleId);

    Сохранение Базы данных

    Чтобы сохранять базу данных, используйте AcDbDatabase:: saveAs () функция:
    Acad:: ErrorStatus
    AcDbDatabase:: saveAs (char* имя файла);
    Имя файла может быть путь к местному файлу, или адресу Internet.

    Сохранение Объектов в DWG и DXF файлах

    При наследовании класса от AcDbObject, Вы нуждаетесь в дополнительной информации относительно AutoCAD файловый механизм, обеспеченный в этой главе. Следующий четыре функции используются для записи в файл объектов к DWG и DXF файлам.
    Они также используются для других целей, типа имитации.
    Acad::ErrorStatus
    AcDbObject::dwgOut(AcDbDwgFiler* filer);
    Acad::ErrorStatus
    AcDbObject::dwgIn(AcDbDwgFiler* filer);
    Acad::ErrorStatus
    AcDbObject::dxfOut(
    AcDbDxfFiler* filer,
    Adesk::Boolean allXdFlag,
    Adesk::uchar* regAppTable) const);
    Acad::ErrorStatus
    AcDbObject::dxfIn(AcDbDxfFiler* filer);
    Каждая функция берет указатель на файл как первый параметр. AcDbObject записывает данные к и читает данные от файла. FilerType перечисление позволяет Вам задать тип файла:
    · kFileFiler (used for DWG and DXF files)
    · kCopyFiler
    · kUndoFiler
    · kBagFiler (used with acdbEntMake(), acdbEntMod(), and acdbEntGet())
    · kIdXlateFiler
    · kPageFiler
    · kDeepCloneFiler
    · kWBlockCloneFiler
    · kPurgeFiler
    DwgOut () и dwgIn () функции в свою очередь вызывают dwgOutFields () и dwgInFields (), соответственно, и DXF, файловые функции вызывают аналогичный набор функций для DXF. Если Вы получаете класс пользователя от AcDbObject, Вы будете должны отменить следующие виртуальные функции, которые используются для постоянного хранения объектов также как для копирования и отменяют операции:
  • dwgOutFields ()

  • dwgInFields ()

  • dxfOutFields ()

  • dxfInFields
    ()


  • Сокрытие Диалоговых окон

    Пользователь не может делать интерактивный выбор, в то время как диалоговое окно активно. Если Вы хотите, чтобы  пользователь делал выбор из графического экрана, Вы должны скрыть ваше диалоговое окно и затем восстанавливать это. Сокрытие поля - тот же самый как окончание этого с ads_done_dialog (), за исключением того, что ваша функция повторного вызова должна использовать ads_done_dialog () параметр состояния, чтобы указать, что диалоговое окно скрыто — в противоположность законченному или отменено. Состояние Набора к приложению - определенное значение.
    Ads_start_dialog () функция возвращает определенное приложением состояние, когда диалоговое окно исчезает. Ваша программа должна тогда исследовать состояние, возвращенное ads_start_dialog () чтобы определить следующее действие.
    Следующая типовая программа имеет кнопку, Выбирать Точку, которая скрывает диалоговое окно так, чтобы пользователь мог определить точку на графическом экране. Действие отбора этой кнопки заставляет диалоговое окно заканчиваться специальным состоянием 4:
    ads_real x_pt, y_pt, z_pt;
    ads_point pick_pt;
    ads_hdlg hdlg;
    int what_next;
    static void CALLB
    pick_callback(ads_callback_packet *cpkt)
    {
    ads_done_dialog(cpkt->dialog, 4);
    }
    void
    bmake_handler()
    {
    // Load dialog box and do global initialization
    //
    while (what_next >= DLGSTATUS) {
    // Indicates custom return code
    // Other initialization such as ads_new_dialog(),
    // ads_action_tile(), ads_set_tile(), and
    // ads_start_list() calls.
    //
    ads_start_dialog(hdlg, &what_next);
    switch (what_next) {
    case 4:
    acedGetPoint(NULL, "Insertion base point: ",
    pick_pt);
    acdbRToS(pick_pt[X], 2, 4, x_pt);
    acdbRToS(pick_pt[Y], 2, 4, y_pt);
    acdbRToS(pick_pt[Z], 2, 4, z_pt);
    break;
    ...
    }
    }
    }
    Следующий пример скрывает множественные диалоговые окна:
    // Глобальные переменные
    //
    Ads_point pick_pt;
    // Они должны быть глобальная переменная, потому что subdlg_handler () функция должен
    //  быть способным обратиться к ним также как основной функции диалога.

    //

    ads_hdlg mdlg;

    int dcl_id, what_next;

    static void CALLB

    hide_handler(ads_callback_packet *cpkt)

    {

    ads_done_dialog(cpkt->dialog, 3);

    }

    static void CALLB

    subdlg_handler(ads_callback_packet *cpkt)

    {

    // REMEMBER: This function must never reference anything in

    // the cpkt packet because none of its fields are valid when

    // it is called explicitly in the main dialog function.

    //

    ads_hdlg sdlg;

    ads_new_dialog("subdlg", dcl_id, NULLCB, &sdlg);

    ads_action_tile(sdlg, "hide_all", hide_handler);

    ads_start_dialog(sdlg, &what_next1);

    if (what_next1 == 3) // Nested hide is in progress. */

    ads_done_dialog(mdlg, DLGSTATUS); // Hide main dialog box.

    }

    void

    maindlg_handler()

    {

    int what_next;

    ads_callback_packet dummy_pkt;

    // dummy_pkt is used when this section of code explicitly calls the

    // subdlg_handler() function. The subdlg_handler() function expects

    // a single parameter that is a pointer to an ads_callback_packet.

    // Normally a callback function is called by AutoCAD, and AutoCAD

    // provides a filled-in packet, but in this code we need to call

    // the callback function explicitly in order to redisplay the

    // subdialog after a hide. In order to do this we need a dummy

    // ads_callback_packet. It doesn’t have to be filled in because

    // none of its fields is ever used.

    //

    ads_load_dialog("maindlg.dcl", &dcl_id);

    what_next = what_next1 = 5; // could be set to anything > 1.

    while (what_next >= DLGSTATUS) { //DLGSTATUS == 2.

    ads_new_dialog("maindlg", dcl_id, NULLCB, &mdlg);

    ads_action_tile(mdlg, "x", subdlg_handler);

    if (what_next1 == 3) {

    // This is only true on returning from a nested hide.

    // Since we are returning from a nested hide,restart the

    // subdialog.

    // Note that the main dialog has NOT been started yet.

    // It is just a bit map painted on screen (it needs an

    // ads_start_dialog() for interactivity).

    //

    subdlg_handler(&dummy_pkt);

    if (what_next1 != 3) {

    // OK or CANCEL pressed to exit the subdialog

    // so it is time to activate the main dialog that

    // was painted but not started.

    //

    ads_start_dialog(mdlg, &what_next);

    }

    } else {

    // this is executed only once upon startup of this whole

    // dialog code.

    //

    ads_start_dialog(mdlg, &what_next);

    }

    if (what_next == DLGSTATUS) { /* DLGSTATUS == 2 */

    // This if condition is true when a nested hide is

    // in progress and both dialogs are hidden.

    //

    ads_getpoint(NULL, "\nPick a point: ", pick_pt);

    }

    }

    ads_unload_dialog(dcl_id);

    }

    Сопоставление подстановочных знаков

    AcutWcMatch() функция позволяет приложениям сравнить строку с образцом подстановочных знаков. Это средство может использоваться при формировании набора выборов (в конъюнкции с acedSSGet ()) и при поиске расширенных данных примитива прикладным именем (в конъюнкции с acdbEntGetX ()).
    AcutWcMatch () функция сравнивает отдельную строку с образцом, и возвращает RTNORM, если строка соответствует образцу, и RTERROR, если это делает нет.
    Образцы подстановочных знаков подобны регулярным выражениям, используемым системой и прикладными программами. В образце, с алфавитными символами и цифры обращаются буквально; скобки могут использоваться, чтобы определить необязательные символы или диапазон символов или цифр; вопросительный знак (?) соответствует единственному символу и звездочка (*) соответствует последовательности символов; уверенный другие специальные символы имеют значения в пределах образца. Для полной таблицы символов, используемых в строках подстановочных знаков, см. описание acutWcMatch ().
    В следующих примерах, строковая переменная вызвала matchme,  был объявлен и инициализирован. Следующий запрос проверяет, начинается ли matchme с этих пяти символов “allof”.
    if (acutWcMatch(matchme, "allof*") == RTNORM) {
    .
    .
    .
    }
    Следующий запрос иллюстрирует использование скобок в образце. В этом случае, acutWcMatch () возвращает RTNORM, если matchme равняется “STR1”, “STR2”, “STR3”, или “STR8”.
    if (acutWcMatch(matchme, "STR[1-38]") == RTNORM) {
    .
    .
    .
    }
    Строка образца может определить множественные образцы, отделенные запятыми. Следующий запрос возвращает RTNORM, если matchme равняется “ABC”, если это начинается с “XYZ”, или если это заканчивается “123”.
    if (acutWcMatch(matchme, "ABC,XYZ*,*123") == RTNORM) {
    .
    .
    .
    }
    AcutWcMatchEx () функция подобна acutWcMatch (), но это имеет дополнительный параметр, чтобы позволить этому игнорировать регистр.
    bool
    acutWcMatchEx(
    const char * string,
    const char * pattern,
    bool ignoreCase);

    Создайте ActiveX Проект Библиотеки Шаблона

    1 Создают новый проект в Visual C++, используя COM ATL AppWizard. Для этого примера, мы назовем проект AsdkDesignCenterSamp. Выбрал тип сервера DLL и Поддержку MFC. Это не требовано, чтобы использовать MFC, но для этой выборки, мы будем использовать это, чтобы делать вещи проще. Нажмите Finish и затем OK создавать проект.
    2 Затем добавляют необходимые изменения, чтобы делать проект ObjectARX совместимым.
    Это включает добавление следующего входного кода в конец AsdkDesignCenterSamp.cpp file:
    extern "C" AcRx::AppRetCode
    acrxEntryPoint(AcRx::AppMsgCode msg, void* appId)
    {
    switch(msg)
    {
    case AcRx::kInitAppMsg:
    acrxRegisterAppMDIAware(appId);
    break;
    case AcRx::kUnloadAppMsg:
    break;
    default:
    break;
    }
    return AcRx::kRetOK;
    }
    3 Вы будете также должны добавить соответствующие назначения к проекту и экспортировать следующие символы в файле определения (.def):
    acrxEntryPoint
    _SetacrxPtp
    acrxGetApiVersion

    Создайте ObjectARX MFC Прикладной Скелет

    1 Создают новый проект в Microsoft Visual C++, используя Прикладного Мастера. Выберите MFC AppWizard (dll) проектный{*строительный*} тип. Назначите проект имя (для этой выборки, мы будем использовать имя AsdkAcUiSample) и каталог и нажимать OK. На следующем экране, выберите Расширение{*продление*} MFC DLL, затем нажмите Finish. Мы теперь имеем основное MFC Расширение{*продление*} DLL проект.
    2 Мы теперь добавим необходимый код, чтобы поддержать ObjectARX. Откройте AsdkAcUiSample.cpp файл. Удалите запрос AFX_EXTENSION_MODULE и также функция DllMain.
    3 Добавляют следующее объявление:
     AC_IMPLEMENT_EXTENSION_MODULE(theArxDLL);
    4 Добавляют следующий код, чтобы установить команду AutoCAD и acrxEntryPoint:
    void dialogCreate()
    {
    acutPrintf("\nAcUi Dialog Sample");
    }
    Следующий запрос addCommand использует образец ресурса модуля от
    AC_IMPLEMENT_EXTENSION_MODULE макрокоманда:
    static void initApp()
    {
    theArxDLL.AttachInstance();
    CAcModuleResourceOverride resOverride;
    acedRegCmds->addCommand(
    "ASDK_ACUI_SAMPLE",
    "ASDKACUISAMPLE",
    "ACUISAMPLE",
    ACRX_CMD_MODAL,
    dialogCreate,
    NULL,
    -1,
    theArxDLL.ModuleResourceInstance());
    }
    Следующий unloadApp () функция вызвана, когда приложение разгружается.
    В это время важно отделить образец ресурса:
    static void unloadApp()
    {
    // Do other cleanup tasks here
    acedRegCmds->removeGroup("ASDK_ACUI_SAMPLE");
    theArxDLL.DetachInstance();
    }
    // Entry point
    //
    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;
    case AcRx::kInitDialogMsg:
    break;
    default:
    break;
    }
    return AcRx::kRetOK;
    }
    Создайте AsdkAcUiSample.h файл заголовка, и добавьте следующие линии к file:
    #include "resource.h" // main symbols
    #define PI 3.14159265359
    // Forward declaration for the entry point function of
    // our application
    void testCreate();
    Тогда добавьте следующие файлы для включения к AsdkAcUiSample.cpp:
    #include "AsdkAcUiSample.h"
    #include "AcExtensionModule.h"
    Вы будете также должны добавить ObjectARX библиотеки к проектному файлу, заменять .dll расширение к .arx, и изменять .def файл надлежащим экспортом.  Тогда Вы должны быть способны компилировать и загрузить приложение.

    Создайте Обработчики для Диалога

    1 Возвращаются в ClassWizard и выбирают позицию табуляции Message Maps.
    2 Высвечивают объект AsdkAcUiDialogSample ИДЕНТИФИКАТОР и добавляют функцию для WM_INITDIALOG. Тогда выберите код редактирования, чтобы брать Вас в AsdkAcUiDialogSample.cpp исходный файл.
    3 Изменяют{*заменяют*} родителя ОнИнитДиалога, чтобы быть CACUIDIALOG:
    CAcUiDialog:: OnInitDialog ();
    4 Изменяют{*заменяют*} конструктор, чтобы также инициализировать CACUIDIALOG:
    AsdkAcUiDialogSample::AsdkAcUiDialogSample
    (CWnd* pParent /*=NULL*/)
    : CAcUiDialog(AsdkAcUiDialogSample::IDD, pParent)
    Следующий шаг должен добавить обработчики сообщения для IDC_BUTTON_ANGLE,
    IDC_BUTTON_POINT, IDC_COMBO_REGAPPS, IDC_EDIT_ANGLE, и IDC_OK ресурсы. Использование ClassWizard, добавьте обработчики, отображенные следующим образом:
    Message handlers

    Handler Function
    Resource ID
    Message
    OnButtonAngle
    IDC_BUTTON_ANGLE
    BN_CLICKED
    OnButtonPoint
    IDC_BUTTON_POINT
    BN_CLICKED
    OnOk
    IDOK
    BN_CLICKED
    OnKillfocusComboRegapps
    IDC_COMBO_REGAPPS
    CBN_KILLFOCUS
    OnKillfocusEditAngle
    IDC_EDIT_ANGLE
    EN_KILLFOCUS
    OnKillfocusEditXpt
    IDC_EDIT_XPOINT
    EN_KILLFOCUS
    OnKillfocusEditYpt
    IDC_EDIT_YPOINT
    EN_KILLFOCUS
    OnKillfocusEditZpt
    IDC_EDIT_ZPOINT
    EN_KILLFOCUS


    Создание Дополнительных клавиш AutoCAD и Значений

    Программа инсталляции приложения ObjectARX должна быть разработана{*предназначена*}, чтобы управлять набором клавиш{*ключей*} и значений для того приложения в пределах раздела системного системного реестра для каждой версии AutoCAD, с которым предназначено работать. Следующий пример показывает размещению клавиш{*ключей*} и значений в разделе системного реестра, который должен быть создан и поддерживаться для приложения:
     \\HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\releaseNum\
    ACAD-1:LocaleID\
    Applications\
    ApplicationName\
    LoadCtrls:REG_DWORD:acrxAppLoadReason
     RegPath:REG_SZ:RegistryPathWhereLoaderIsSpecified
    ReleaseNum и клавиши{*ключи*} ACAD-1:LocaleID созданы программой инсталляции AutoCAD. Клавиша{*ключ*} ApplicationName должна быть логическое название{*имя*} приложения, которое используется внутренне в соответствии с AutoCAD, чтобы идентифицировать программу. Значение acrxAppLoadReason определяет условия, при которых приложение будет загружено, используя один или более логический ORS следующих шестнадцатеричных значений, перечисленных с их связанными значениями:
    0x01 Загружают приложение после обнаружения полномочного объекта{*цели*}.
    0x02 Загружают приложение после запуска AutoCAD.
    0x04 Загружают приложение на обращение команды.
    0x08 Загружают приложение по запросу пользователем или другим приложением.
    0x10 Не загружают приложение.
    Значение RegistryPathWhereLoaderIsSpecified должно идентифицировать путь системного реестра для собственного раздела приложения системного реестра.
    ObjectARX API включает acrxRegisterApp () функция, которая может использоваться в Приложении ObjectArx, чтобы ввести информацию относительно приложения в раздел AutoCAD системного реестра. Как правило, acrxRegisterApp () ввел бы эту информацию,  первый раз, когда приложение загружен, и подтверждать присутствие той информации относительно последующих загрузок.

    Создание Файла Системного реестра

    Для вашего сервера COM, чтобы быть полностью функциональный, все компоненты и их соответствующие интерфейсы должны быть зарегистрированы с системой. Кроме того, библиотека типов должна также быть зарегистрирована так, чтобы это могло использоваться, чтобы осуществить IDISPATCH для ваших компонентов.
    Вхождения системного реестра типично создаются в течение инсталляции вашего программного обеспечения.
    Ниже Вас найдет, что информация помогает создает файл системного реестра (.reg), который является высоко полезным и идентифицирует минимальное количество информации, требуемой для вашего сервера COM.
    Общий формат (использование compoly.reg как пример):
    REGEDIT
    ; type library entries
    HKEY_CLASSES_ROOT\TypeLib\{uuid of type library}
    HKEY_CLASSES_ROOT\TypeLib\{uuid of type library}\1.0 =
    compoly 1.0 Type Library HKEY_CLASSES_ROOT\TypeLib\
    {uuid of type library}\1.0\HELPDIR = x:\some\path\to
    HKEY_CLASSES_ROOT\TypeLib\{uuid of type library}\1.0\0\win32 =
    x:\some\path\to\compoly.tlb
    HKEY_CLASSES_ROOT\TypeLib\{uuid of type library}\1.0\9\win32 =
    x:\some\path\to\compoly.tlb
    ; coclass entries
    HKEY_CLASSES_ROOT\CLSID\{uuid of coclass} = ComPolygon Class
    HKEY_CLASSES_ROOT\CLSID\{uuid of coclass}\InProcServer32 =
    x:\some\path\to\compoly.dll
    ; interface entries
    HKEY_CLASSES_ROOT\Interface\{uuid of interface} =
    IComPolygon Interface
    HKEY_CLASSES_ROOT\Interface\{uuid of interface}\TypeLib =
    {uuid of type library}
    HKEY_CLASSES_ROOT\Interface\{uuid of interface}\ProxyStubClsid32 =
    {00020424-0000-0000-C000-000000000046}
    Последние две секции повторятся для каждого coclass и связывать с помощью интерфейса в вашей библиотеке типов. Файл IDL имел обыкновение формировать библиотеку типов, будет содержать весь uuids, который Вы должны заполнить пробелы выше. Ниже прокомментированы выборки от compoly.idl, которые идентифицируют каждый uuid.
    [
    // uuid of type lib.
    //
    uuid(45C7F028-CD9A-11D1-A2BD-080009DC639A),
    version(1.0),
    helpstring("compoly 1.0 Type Library")
    ]
    library COMPOLYLib
    {
    // ... Code cut out for brevity.
    // IComPolygon interface
    [
    object,
    // uuid of interface
    //
    uuid(45C7F035-CD9A-11D1-A2BD-080009DC639A),
    dual,
    helpstring("IComPolygon Interface"),
    pointer_default(unique)
    ]
    interface IComPolygon : IAcadEntity
    {
    // ... Code cut out for brevity.
    };
    // ... Code cut out for brevity.
    // ComPolygon coclass
    [
    // uuid of coclass
    //
    uuid(45C7F036-CD9A-11D1-A2BD-080009DC639A),
    helpstring("ComPolygon Class"),
    noncreatable
    ]
    coclass ComPolygon
    {
    [default] interface IComPolygon;
    [source] interface IAcadObjectEvents;
    };
    };

    Создание и cтирание cписка

    ObjectARX-приложение может динамически размещать единственный буфер результатов,  вызывая acutNewRb (). Запрос к acutNewRb () должен определить тип буфера, чтобы разместить; acutNewRb () автоматически инициализирует restype поле буфера, чтобы содержать указанный код типа.
    Следующий типовой кодовый фрагмент размещает буфер результатов, чтобы содержать трехмерную точку и затем инициализирует значение точки:
    struct resbuf *head;
    if ((head=acutNewRb(RT3DPOINT)) == NULL) {
    acdbFail("Unable to allocate buffer\n");
    return BAD;
    }
    head->resval.rpoint[X] = 15.0;
    head->resval.rpoint[Y] = 16.0;
    head->resval.rpoint[Z] = 11.18;
    Если новый буфер результатов должен содержать строку, приложение должно явно разместить память, чтобы содержать строку:
    struct resbuf *head;
    if ((head=acutNewRb(RTSTR)) == NULL) {
    acdbFail("Unable to allocate buffer\n");
    return BAD;
    }
    if ((head->resval.rstring = malloc(14)) == NULL) {
    acdbFail("Unable to allocate string\n");
    return BAD;
    }
    strcpy(head->resval.rstring, "Hello, there.");
    Память, размещенная для строк, которые связаны с динамическим списком,  выпущена, когда список выпущен, так что следующий запрос выпускает всю память, размещенную в предыдущем примере:
    acutRelRb(head);
    Чтобы выпускать строку без того, чтобы выпустить буфер, вызовите свободным () и установите строковый указатель на NULL как показано в следующем примере:
    free(head->resval.rstring);
    head->resval.rstring = NULL;
    Установка resval.rstring к NULL предотвращает последующий запрос к acutRelRb () из попытки выпустить строку второй раз.
    Если элементы списка известны заранее, более быстрый способ создавать это состоит в том, чтобы вызвать acutBuildList (), который берут переменное число пар параметра (с исключениями типа RTLB, RTLE, -3, и других) и возвращают указатель на список буферов результатов, который содержит указанные типы и значения, связанные вместе в порядке, в котором их пропускали к acutBuildList (). Эта функция размещает память как требовано и инициализирует все значения. Последний параметр к acutBuildList () должен быть единственный параметр, чей значение является или нулем или RTNONE.
    Следующий типовой кодовый фрагмент создает список, который состоит из трех буферов результатов. Они содержат реальное значение, строку, и точку, в том порядке:
    struct resbuf *result;
    ads_point pt1 = {1.0, 2.0, 5.1};
    result = acutBuildList(
    RTREAL, 3.5,
    RTSTR, "Hello, there.",
    RT3DPOINT, pt1,
    0 );
    Если это не может создавать список, acutBuildList () возвращает NULL; иначе, это размещает пространство, чтобы содержать список. Этот список должен быть выпущен последующим запросом к acutRelRb ():
    if (result != NULL)
    acutRelRb(result);

    Создание и Изменение Записи Таблицы Уровня

    Следующие показы примера, получающие таблицу уровня для текущей базы данных и открытия этого для записи. Это создает новую запись таблицы уровня (AcDbLayerTableRecord) и устанавливает некоторые атрибуты уровня (имя, закрепляемый атрибут, вкл\выкл, область просмотра, и блокированный). Тогда это создает цветной объект класса и устанавливает цвет уровня к красному.
    Чтобы устанавливать linetype для уровня, этот пример открывает linetype таблицу для чтения и получает объект ID записи linetype желательный linetype (здесь, “DASHED” - “ПОДЧЕРКНУТЫЙ ШТРИХОВОЙ ЛИНИЕЙ”). Как только это имеет объект ID для linetype, это закрывает linetype таблицу и устанавливает linetype для новой записи таблицы уровня. Этот пример использует добавляющийся () функцию, чтобы добавить запись таблицы уровня на таблицу уровня. Наконец, это закрывает запись таблицы уровня и таблицу уровня непосредственно.
    void
    addLayer()
    {
    AcDbLayerTable *pLayerTbl;
    acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pLayerTbl, AcDb::kForWrite);
    if (!pLayerTbl->has("ASDK_TESTLAYER")) {
    AcDbLayerTableRecord *pLayerTblRcd
    = new AcDbLayerTableRecord;
    pLayerTblRcd->setName("ASDK_TESTLAYER");
    pLayerTblRcd->setIsFrozen(0);// layer to THAWED
    pLayerTblRcd->setIsOff(0); // layer to ON
    pLayerTblRcd->setVPDFLT(0); // viewport default
    pLayerTblRcd->setIsLocked(0);// un-locked
    AcCmColor color;
    color.setColorIndex(1); // set color to red
    pLayerTblRcd->setColor(color);
    // For linetype, we need to provide the object ID of
    // the linetype record for the linetype we want to
    // use. First, we need to get the object ID.
    //
    AcDbLinetypeTable *pLinetypeTbl;
    AcDbObjectId ltId;
    acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pLinetypeTbl, AcDb::kForRead);
    if ((pLinetypeTbl->getAt("DASHED", ltId))
    != Acad::eOk)
    {
    acutPrintf("\nUnable to find DASHED"
    " linetype. Using CONTINUOUS");
    // CONTINUOUS is in every drawing, so use it.
    //
    pLinetypeTbl->getAt("CONTINUOUS", ltId);
    }
    pLinetypeTbl->close();
    pLayerTblRcd->setLinetypeObjectId(ltId);
    pLayerTbl->add(pLayerTblRcd);
    pLayerTblRcd->close();
    pLayerTbl->close();
    } else {
    pLayerTbl->close();
    acutPrintf("\nlayer already exists");
    }
    }

    Создание и Начальная загрузка Базы данных

    Используйте new, чтобы создать базу данных и delete, чтобы уничтожить ее. AcDbDatabase конструктор имеет один параметр со значением по умолчанию Adesk:: kTrue. Если этот параметр - Adesk:: kTrue, то база данных заполняется со стандартными объектами базы данных, описана в “ Начальная База данных. ”, если параметр - Adesk:: kFalse, то пустая база данных создана и может заполняться,  считывая чертежный файл.
    Используйте следующую функцию, чтобы читать в чертежном файле:
    AcadErrorStatus
    AcDbDatabase::readDwgFile(char* fileName);
    Если Вы получаете любой из кодов ошибки слежения, Вы вероятно хотите возвратить рисунок к стандарту, AutoCAD возвращает механизм, обеспеченный интерфейсом пользователя:
    KDwgNeedsRecovery
    KDwgCRCDoesNotMatch
    KDwgSentinelDoesNotMatch
    KdwgObjectImproperlyRead
    ПРЕДУПРЕЖДЕНИЕ! Никогда не удалите базу данных, возвращенную acdbHostApplicationServices()->workingDatabase().

    Создание изображения

    Последовательность запроса, чтобы создать изображения для полей ввода изображения и кнопок изображения подобна обрабатывающей списку последовательности. Ads_start_image () функция начинает создание изображения, и ads_end_image () заканчивает это. Однако, опции для того, чтобы рисовать определены следующей отдельной функцией, вызывает вместо параметров:
    §
    N ads_vector_image () рисует вектор (единственный, прямо выравнивать) в текущем изображении.
    § N ads_fill_image () рисует заполненный прямоугольник в текущем изображении.
    § N ads_slide_image () рисует слайд AutoCAD в изображении.
    Векторы и заполненные прямоугольники полезны для простых изображений, типа цветных образчиков (заполненные прямоугольники) использования диалогового окна AutoCAD Select Color, чтобы отобразить выбор пользователя цвета. Для сложных изображений, слайды более удобны. Однако их отображение может быть потребление время. Если Вы используете их, сохраните их простой.
    Рисующая изображение функция, ads_vector_image (), требует, чтобы Вы определили абсолютные координаты, в то время как ads_fill_image () и ads_slide_image () требуют стартовой координаты с относительной шириной и высотой. Чтобы делать это правильно, Вы должны знать точные измерения о поле ввода изображения или кнопке изображения. Поскольку эти измерения обычно назначаются, когда диалоговое окно размещено, пакет PDB обеспечивает функцию, ads_dimensions_tile (), который возвращает ширину и высоту специфического поля ввода. Вызовите эту функцию прежде, чем Вы начинаете создавать изображение. Начало координат поля ввода (0,0), является всегда его левым верхним углом.
    Цвета могут быть определены как номера цвета AutoCAD или как один из “логических” номеров цвета, показанных в следующей таблице.
    ADI
    номера цвета



    Цвет

    Номер

    Мнемоническое описание ADI

    -2

    BGLCOLOR

    Текущий фон экрана графики AutoCAD

    -15

    DBGLCOLOR

    Текущий цвет фона диалогового окна

    -16

    DFGLCOLOR

    Цвет символа диалогового окна Current (для текста)

    -18

    LINELCOLOR

    Диалоговое окно текущего цвета линии
    <
    Значения и мнемоника определены Интерфейсом Устройства Autodesk (ADI).

    В следующем примере, “cur_color” - поле ввода изображения, которое будет заполнено полностью заплатой красных. Только один запрос необходим, чтобы получить измерения изображения:

    short width, height;

    ads_dimensions_tile(hdlg, "cur_color", &width, &height);

    ads_start_image(hdlg, "cur_color");

    ads_fill_image(0, 0, width, height, 1); // 1 == red.

    ads_end_image();

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

    short width, height, x;

    ads_dimensions_tile(hdlg, "stripe", &width, &height);

    ads_start_image(hdlg, "stripe");

    ads_fill_image(0, 0, 0, height, 3); // 3 == AutoCAD green.

    // Center the vector vertically.

    //

    x = width/2;

    ads_vector_image(x, 0, x, height, 4); // 4 == cyan.

    ads_end_image();

    Скольжения, которые Вы отображаете с ads_slide_image () могут быть автономное скольжение (.sld) файлы или часть библиотеки скольжений (.slb) файл. Если скольжение находится в .sld файле, Вы определяете его имя без .sld расширения (например, “frntview”). Если скольжение находится в библиотеке скольжений, Вы определяете имя библиотеки сначала (без расширения), сопровождаемый именем скольжения непосредственно (также без расширения) включенный в круглые скобки (например, “ allviews (frntview) ”). Ads_slide_image () функциональные исследования скольжения или файла библиотеки скольжения согласно потоку путь поиска файлов библиотеки AutoCAD.

    Скольжение в следующем примере находится в отдельном файле, вызвал topview.sld:

    short x, y;

    ads_dimensions_tile(hdlg, "view", &x, &y);

    ads_start_image(hdlg, "view");

    ads_slide_image(0, 0, x, y, "topview");

    ads_end_image();

    Векторы в скольжениях часто рисуются в белом (номер цвета 7), который является заданным по умолчанию цветом фона изображения. Если ваше поле ввода изображения - пробел, когда Вы сначала отображаете скольжение, пробуете изменить его цветной атрибут к graphics_background. (Вы можете также изменять фон изображения,  предшествуя ads_slide_image () запрос с ads_fill_image () запрос).

    Создание классов и средств управления

    1 Использование ClassWizard, создайте диалоговый класс. Если Вы запускаете ClassWizard с экрана создания диалога, это запросит Вас создавать новый класс. Нажмите OK для нового класса, и затем дайте диалогу имя. Для этого примера используют AsdkAcUiDialogSample.
    2 Выключатель к позиции табуляции member variable.
    3 Для IDC_BUTTON_ANGLE и IDC_BUTTON_POINT ресурсов добавляют, что средство управления CBUTTON вызвало m_ctrlAngleButton и m_ctrlPickButton, соответственно.
    4 Для IDC_EDIT_ANGLE, IDC_EDIT_XPT, IDC_EDIT_YPT, и IDC_EDIT_ZPT ресурсов добавляют, что средство управления CEDIT вызвало m_ctrlAngleEdit, m_ctrlXPtEdit, m_ctrlYPtEdit, и m_ctrlZPtEdit, соответственно.
    5 Для IDC_LIST_BLOCKS ресурса добавляют, что управление CLISTBOX вызвало m_ctrlBlockList.
    6 Для IDC_COMBO_REGAPPS ресурса добавляют, что управление CCOMBOBOX вызвало m_ctrlRegAppComboBox.
    7 Теперь открывают AsdkAcUiDialogSample.h файл заголовка и заменяют образование из нового диалогового класса. Это должно быть получено из CACUIDIALOG:
    class AsdkAcUiDialogSample : public CAcUiDialog
    8 Теперь мы изменим{*заменим*} типы, чтобы использовать средство управления AcUi. Начало,  открывая AsdkAcUiDialogSample.h файл. Измените{*замените*} список управления, чтобы быть следующим:
    CAcUiSymbolComboBox  m_ctrlRegAppComboBox;
    CacUiListBox        m_ctrlBlockListBox;
    CAcUiPickButton m_ctrlPickButton;
    CacUiPickButton   m_ctrlAngleButton;
    CacUiAngleEdit    m_ctrlAngleEdit;
    CAcUiNumericEdit m_ctrlXPtEdit;
    CAcUiNumericEdit m_ctrlYPtEdit;
    CAcUiNumericEdit m_ctrlZPtEdit;
    9 Также добавляют пару полей, чтобы проследить точку и угловые значения и некоторые функции помощника. Они должны быть добавлены к общественному разделу класса:
    AcGePoint3d m_ptValue;
    double m_dAngle;
    void DisplayPoint();
    bool ValidatePoint();
    void DisplayAngle();
    bool ValidateAngle();
    void DisplayBlocks();
    void DisplayRegApps();

    Создание Классов Расширения Протокола

    Чтобы создавать заказной режим объектной привязки, Вы должны создать классы расширения протокола, чтобы обработать входную точку "в юридическое лицо" обработка. Класс AcDbCustomOsnapInfo определяет протокол, который каждый заказной режим объектной привязки должен осуществить для уместных примитивов. Этот базовый класс содержит функцию getOsnapInfo (), который исполняет входную обработку точки на примитиве:
    class AcDbCustomOsnapInfo : public AcRxObject {
    public:
    ACRX_DECLARE_MEMBERS(AcDbCustomOsnapInfo);
    virtual Acad::ErrorStatus
    getOsnapInfo(
    AcDbEntity* pickedObject,
    int gsSelectionMark,
    const AcGePoint3d& pickPoint,
    const AcGePoint3d& lastPoint,
    const AcGeMatrix3d& viewXform,
    AcArray& snapPoints,
    AcArray& geomIdsForPts,
    AcArray& snapLines,
    AcArray& geomIdsForLines);
    };
    Создавать расширение протокола классифицирует для заказных режимов объектной привязки
    1 Определяют абстрактный класс расширения протокола, полученный из AcDbCustomOsnapInfo.
    Например, если ваш класс пользователя назван AcmeSocketInfo, определите это следующим образом:
    class AcmeSocketInfo : public AcDbCustomOsnapInfo{
    public:
    ACRX_DECLARE_MEMBERS(AcDbSocketInfo);
    virtual Acad::ErrorStatus
    getOsnapInfo(
    AcDbEntity* pickedObject,
    int gsSelectionMark,
    const AcGePoint3d& pickPoint,
    const AcGePoint3d& lastPoint,
    const AcGeMatrix3d& viewXform,
    AcArray& snapPoints,
    AcArray& geomIdsForPts,
    AcArray& snapLines,
    AcArray& geomIdsForLines);
    };
    ACRX_NO_CONS_DEFINE_MEMBERS(AcmeSocketInfo, AcDbCustomOsnapInfo);
    2 Инициализируют основной класс расширения протокола и добавляют это к иерархии классов во время выполнения.
    Например, добавьте следующие линии к вашему acrxEntryPoint () функция:
    AcmeSocketInfo::rxInit();
    acrxBuildClassHierarchy();
    3 Для каждого уместного класса примитива, получите класс расширения протокола из базового класса.
    Например, Вы могли бы получать класс по имени AcmeSocketForLines, который осуществляет getOsnapInfo () чтобы обработать входную обработку точки для линий.
    ОБРАТИТЕ ВНИМАНИЕ, что заданное по умолчанию выполнение должно быть связано с AcDbEntity для каждого зарегистрированного класса, полученного из AcDbCustomOsnapInfo.
    4 Создают образец каждого объекта расширения протокола и добавляют объекты к соответствующим AcRxClass дескрипторным объектам, использующим addX () функция.
    Например:
    pSocketForLine = new AcmeSocketForLine;
    AcDbLine::desc()->addX(AcmeSocketInfo::desc(), pSocketForLine);

    Создание ключей и значений приложения ObjectArx

    Программа инсталляции приложения ObjectARX должна быть разработана, чтобы управлять разделом приложения системного реестра. Этот раздел системного реестра должен включить клавиши{*ключи*} и значения, идентифицирующие основной модуль приложения и набора команд для приложения.
    Значение в клавише{*ключе*} Loader должно включить полный путь и имя файла модуля, который AutoCAD должен загрузиться сначала. Модуль загрузчика впоследствии ответствен за загрузку любых других модулей, которые составляют приложение.
    Следующий пример иллюстрирует размещение и типы значения прикладного раздела системного системного реестра:
    \\ HKEY_LOCAL_MACHINE\SOFTWARE\
    ...
    RegistryPathWhereLoaderIsIdentified\
    Loader\Module:REG_SZ:DirPathFileName
    Name\DescriptiveName:REG_SZ:User Friendly App Name
    Commands\GlobalCommandName1:REG_SZ:LocalCommandName1
    GlobalCommandName2:REG_SZ:LocalCommandName2
    GlobalCommandName3:REG_SZ:LocalCommandName3
    GlobalCommandName4:REG_SZ:LocalCommandName4
    GlobalCommandName5:REG_SZ:LocalCommandName5
    Groups\
    GroupName:REG_SZ:GroupName
    ...
     Значение Модуля должно присутствовать, но не используется кроме как метка - заполнитель в системном реестре. Точно так же Название{*имя*} Приложения Дружественный к пользователю должно присутствовать, но в настоящее время не используется.
    Значение в клавише{*ключе*} Groups может использоваться, чтобы уникально идентифицировать группы команд приложений ObjectARX и поэтому команды также.

    Создание MFC-диалога, используя Visual Studio

    1 В Visual C++ добавляют ресурс диалога.
    2 Создают следующее диалоговое окно, используя средство управления Студии Приложения:
    Создание MFC-диалога, используя Visual Studio
    3 Удостоверятся ресурс, ИДЕНТИФИКАТОРЫ соответствуют{*согласовывают*} этой диаграмме, или остающийся код не будет работать.

    Создание Неповторно используемой Команды

    Делать команду неповторно используемой
    1 Объявляют статическую Булеву переменную в вашем приложении для каждой команды, Вы желаете быть неповторно используемыми. Статически инициализируйте каждую переменную к FALSE.
    2 Всякий раз, когда пользователь вводит команду или действие, Вы хотите предотвратить повторную входимость к, сначала проверять{*отмечать*} его статическую Булеву переменную. Если это - FALSE, устанавливает это в TRUE и продолжает команду. Если это - TRUE, команда повторно вводится, так перенесите сообщение, спрашивающее пользователя, чтобы закончить команду в другом документе, в котором это используется.
    3 Всегда задерживают Булеву переменную к FALSE, когда команда закончена, отменена, или заканчивается по любой причине.

    Создание Нового Уровня

    Следующий код получает таблицу идентификаторов уровня от базы данных, создает новую запись таблицы уровня ASDK_MYLAYER.
    void
    createNewLayer()
    {
    AcDbLayerTable *pLayerTable;
    acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pLayerTable, AcDb::kForWrite);
    AcDbLayerTableRecord *pLayerTableRecord =
    new AcDbLayerTableRecord;
    pLayerTableRecord->setName("ASDK_MYLAYER");
    // Defaults are used for other properties of
    // the layer if they are not otherwise specified.
    //
    pLayerTable->add(pLayerTableRecord);
    pLayerTable->close();
    pLayerTableRecord->close();
    }

    Создание Новой Базы данных от Существующей Базы данных

    Следующая функция - эквивалент команды WBLOCK*:
    Acad:: ErrorStatus
     AcDbDatabase::wblock(AcDbDatabase*& NewDb);
    Эта функция создает новую базу данных от вызванной базы данных ("this").
    Любые неупомянутые символы во входной базе данных опущены в новой базе данных (который делает новую базу данных потенциально уборщиком и меньший чем оригинал). Однако, это не заботится о копировании определенных приложением объектов, чей монопольное использование внедрено в названном объектном словаре. Вы должны передать{*переместить*} данные прикладной программы от исходной базы данных до целевой базы данных, используя AcEditorReactor функции уведомления.

    Создание Объекта COM

    API Автоматизации ответствен за создание соответствующего объекта COM для данного объекта резидента базы. AutoCAD осуществляет набор интерфейсов для всех объектов резидента базы данных с соответствующими компонентами Автоматизации.
    Многие из этих интерфейсов будут осуществлены автоматически для ваш AcDbObject-получаемый или AcDbEntity полученный класс, когда Вы используете ATL-ОСНОВАННЫЕ обеспеченные шаблоны.
    При создании расширений{*продлений*} к API Автоматизации, Вы могут были должны создать объект COM для данного указателя AcDbObjectId или AcDbObject. Это может быть сделано, используя CoCreateInstance сопровождаемый при помощи AcAxOleLinkManager и IACADBASEOBJECT, чтобы основать соответствующие связи. Следующие функции экспортируются для этой цели:
    // Получить IUNKNOWN
    существующего объекта COM (или недавно созданный объект COM,
    // если не существуете) который представляет AcDbObject, пропускал{*прошел*} в.
    //
    HRESULT
    AcAxGetIUnknownOfObject(LPUNKNOWN* ppUnk, AcDbObjectId& objId,
    LPDISPATCH pApp);
    HRESULT
    AcAxGetIUnknownOfObject(LPUNKNOWN* ppUnk, AcDbObject* pObj,
    LPDISPATCH pApp);
    Объекты COM созданы через CoCreateInstance () использование CLSID, который идентифицирует тип объекта. Чтобы отыскивать передачу CLSID для данного объекта AcDbObject-derived, используйте его getClassID () функция. Эта функция определена на уровне AcDbObject и перегружена на каждом другом уровне в иерархии классов, которая имеет различный тип объекта COM, чтобы представить это.
    // Получить соответствующий класс обертки COM ID.
    //
    virtual Acad::ErrorStatus getClassID(CLSID* pClsid) const;
    Например, если Вы создаете заказной примитив (другими словами, AcDbEntity -dполучил{*происходил*} класс) и не перегружать getClassID (), тогда возвращенный CLSID - тот для AcadEntity. Это означает, что ваши заказные примитивы будут по крайней мере иметь функциональные возможности основного уровня, даже если Вы не обеспечиваете поддержку COM для вашего примитива.
    Имеется дополнительное требование для использования следующих API, чтобы создать объекты COM для вашего AcDbObject-полученного класса:

    IAcadBlock::AddCustomObject(BSTR ClassName, LPDISPATCH* pObject)

    IAcadModelSpace::AddCustomObject(BSTR ClassName,

    LPDISPATCH* pObject)

    IAcadPaperSpace::AddCustomObject(BSTR ClassName,

    LPDISPATCH* pObject)

    CAcadDictionary::AddObject(BSTR Keyword, BSTR ObjectName,

    IAcadObject** pObject)

    Эти функции берут фактическое AcDbObject-полученное имя класса (например, AcDbMyObject) и создают объект COM для Вас. После того, как объект COM создан, IAcadBaseObjectId:: SetObjectId () будет,  обратился к этому, чтобы позволить AcDbObject-полученному классу быть инициализированным и добавлен к базе данных.

    К obtai n CLSID для данного AcDbObject-полученного имени класса, системный реестр системы должен содержать вход с именем вашего AcDbObject и его передачи CLSID значение.

    Размещение системного реестра напоминает это:

    HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\

    ObjectDBX\

    ActiveXCLSID\

    AcRxClassName\CLSID:REG_SZ:

    {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}

    В примере выше, замените AcRxClassName именем вашего AcDbObject-полученного класса (другими словами, AcDbMyObject).

    Создание объектов в AutoCAD

    Этот раздел описывает создание строки, круга, уровня, и группы в AutoCAD и показывает, как AutoCAD прибавляет эти объекты к базе данных. Сначала, предположите, что  пользователь создает строку в модельном пространстве  command: line 4,2 10,7
    В базе данных, AutoCAD создает образец класса AcDbLine и затем сохраняет это в модельном пространственном блочном отчете таблицы как показано:
    Создание объектов в AutoCAD
    Когда Вы сначала вызываете AutoCAD, и база данных находится в ее заданном по умолчанию состоянии, объекты добавлены в пространство модели, основное пространство в AutoCAD, который используется для модельной геометрии и графики. Бумажное пространство предназначено, чтобы поддержать “документационную” геометрию и графику, типа основ пленки для изготовления топологических чертежей, блоков заголовка, и annotational текста. Команды создания объекта в AutoCAD (LINE, в этом случае) заставляют объект быть добавленными к текущей базе данных также как к  блоку пространства модели. Вы можете спрашивать любой объект, принадлежащий базе данных.
    Затем, предположите, что  пользователь создает круг  командой:
    circle 9,3 2
    Снова, AutoCAD создает образец соответствующего объекта — здесь, AcDbCircle — и прибавляет это к пространству модели.
    Создание объектов в AutoCAD
    Затем, пользователь создает уровень:
    layer_make mylayer
     AutoCAD создает новую запись таблицы уровня и затем прибавляет его в таблицу уровней.
    Создание объектов в AutoCAD
    Наконец, группируем все объекты вместе:
    group 3,2 9,3
    AutoCAD создает новую группу и прибавляет ее к словарю GROUP, который содержится в объектном словаре имен. Новая группа содержит список  ID объектов, которые составляют группу.
    Создание объектов в AutoCAD

    Создание приложения ObjectARX

    Приложение ObjectARX - DLL, который совместно использует адресное пространство AutoCAD и делает прямые функциональные запросы к AutoCAD. ObjectARX приложения типично осуществляют команды, к которым можно обращаться изнутри AutoCAD.
    Эти команды часто осуществляются, используя заказные классы. Создание приложения ObjectARX подразумевает следующие общие шаги.
    1. Создайте заказные классы, чтобы осуществить новые команды.
    Вы можете получать заказные классы из большинства таблиц идентификаторов  иерархии классов ObjectARX.
    2. Определите, которые сообщения AutoCAD ваше приложение ObjectARX обработает. AutoCAD посылает разнообразие сообщений к приложениям ObjectARX, указывая, что специфические события произошли в пределах AutoCAD. Вы решаете, которым сообщениям ваше приложение ответит  и которые действия будут вызваны.
    3. Осуществьте точку входа для AutoCAD.
    AutoCAD звонит в приложение ObjectARX через AcrxEntryPoint(), которая заменяет функцию main() программы C++. Вы ответственны за осуществление acrxEntryPoint() в вашем приложении. AcrxEntryPoint() вызывает функции, которые вы связали с определенными сообщениями AutoCAD.
    4. Инициализация реализации.
    В пределах вашего приложения ObjectARX, Вы будете должны инициализировать любые заказные классы, что Вы создали, и восстанавливаете ObjectARX дерево классов во время выполнения. Дополнительно, если Вы прибавляете команды, Вы должны регистрировать их в AutoCAD.
    5. Готовьтесь к разгрузке.
    Чтобы создавать хорошее приложение ObjectARX, Вы должны удалить любые заказные классы и команды, когда ваше приложение разгружено.
    Следующие разделы обсуждают общие шаги разработки приложения ObjectARX более подробно.
    ОБРАТИТЕ ВНИМАНИЕ, что ObjectARX Мастер доступен для создания ObjectARX проекты. См. objectarx\utils каталог в ObjectARX SDK.

    Создание примитивов

    Следующий код ObjectARX создает линию и прибавляет это к  таблице блоков пространства модели:
    AcDbObjectId
    createLine()
    {
    AcGePoint3d startPt(4.0, 2.0, 0.0);
    AcGePoint3d endPt(10.0, 7.0, 0.0);
    AcDbLine *pLine = new AcDbLine(startPt, endPt);
    AcDbBlockTable *pBlockTable;
    acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pBlockTable, AcDb::kForRead);
    AcDbBlockTableRecord *pBlockTableRecord;
    pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord,
    AcDb::kForWrite);
    pBlockTable->close();
    AcDbObjectId lineId;
    pBlockTableRecord->appendAcDbEntity(lineId, pLine);
    pBlockTableRecord->close();
    pLine->close();
    return lineId;
    }
    CreateLine()  получает блочную таблицу для текущего рисунка.
    Тогда это открывает в модельном пространстве  запись блочной таблицы. После закрытия блочной таблицы, это прибавляет объект к блочной  таблице и затем закрывает  таблицу и объект.
    ОБРАТИТЕ ВНИМАНИЕ, когда Вы используете любые объекты ObjectARX, Вы должны  их как можно скорее закрыть.
    createCircle () создает круг и прибавляет это к блочной таблице пространства модели:
    AcDbObjectId createCircle()
    {
    AcGePoint3d center(9.0, 3.0, 0.0);
    AcGeVector3d normal(0.0, 0.0, 1.0);
    AcDbCircle *pCirc = new AcDbCircle(center, normal, 2.0);
    AcDbBlockTable *pBlockTable;
    acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pBlockTable, AcDb::kForRead);
    AcDbBlockTableRecord *pBlockTableRecord;
    pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord,
    AcDb::kForWrite);
    pBlockTable->close();
    AcDbObjectId circleId;
    pBlockTableRecord->appendAcDbEntity(circleId, pCirc);
    pBlockTableRecord->close();
    pCirc->close();
    return circleId;
    }

    Создание Простого Примитива

    Следующий пример демонстрирует создание строки и добавления в конец этого к образцовому пространственному блочному отчету{*записи*} таблицы, как описано в главе 2, “ Учебник для начинающих Базы данных. ”
    AcDbObjectId
    createLine()
    {
    AcGePoint3d startPt(4.0, 2.0, 0.0);
    AcGePoint3d endPt(10.0, 7.0, 0.0);
    AcDbLine *pLine = new AcDbLine(startPt, endPt);
    AcDbBlockTable *pBlockTable;
    acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pBlockTable, AcDb::kForRead);
    AcDbBlockTableRecord *pBlockTableRecord;
    pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord,
    AcDb::kForWrite);
    pBlockTable->close();
    AcDbObjectId lineId;
    pBlockTableRecord->appendAcDbEntity(lineId, pLine);
    pBlockTableRecord->close();
    pLine->close();
    return lineId;
    }

    Создание Словаря

    Следующий пример создает новый словарь (ASDK_DICT) и добавляет это к словари имен объектов. Тогда это создает два новых объекта класса пользователя AsdkMyClass (полученный из AcDbObject) и добавляет их к словарю, используя setAt () функция.
    ОБРАТИТЕ ВНИМАНИЕ, что Вы должны закрыть объекты после добавления их с setAt () функция.
    // This function creates two objects of class AsdkMyClass.
    // It fills them in with the integers 1 and 2, and then adds
    // them to the dictionary associated with the key ASDK_DICT. If this
    // dictionary doesn’t exist, it is created and added to the named
    // object dictionary.
    //
    void
    createDictionary()
    {
    AcDbDictionary *pNamedobj;
    acdbHostApplicationServices()->workingDatabase()->
    getNamedObjectsDictionary(pNamedobj, AcDb::kForWrite);
    // Check to see if the dictionary we want to create is
    // already present. If not, create it and add
    // it to the named object dictionary.
    //
    AcDbDictionary *pDict;
    if (pNamedobj->getAt("ASDK_DICT", (AcDbObject*&) pDict,
    AcDb::kForWrite) == Acad::eKeyNotFound)
    {
    pDict = new AcDbDictionary;
    AcDbObjectId DictId;
    pNamedobj->setAt("ASDK_DICT", pDict, DictId);
    }
    pNamedobj->close();
    if (pDict) {
    // Create new objects to add to the new dictionary,
    // add them, then close them.
    //
    AsdkMyClass *pObj1 = new AsdkMyClass(1);
    AsdkMyClass *pObj2 = new AsdkMyClass(2);
    AcDbObjectId rId1, rId2;
    pDict->setAt("OBJ1", pObj1, rId1);
    pDict->setAt("OBJ2", pObj2, rId2);
    pObj1->close();
    pObj2->close();
    pDict->close();
    }
    }

    Создание Сложного Примитива

    Эти показы примера, как создавать объект AcDb2dPolyline и устан некоторых из его свойств — уровень, окрашивают индекс, закрытый параметр. Это тогда создает четыре объекта (AcDb2dPolylineVertex вершины, устанавливает их местоположение, и добавляет их к объекту ломаной линии. Наконец, это закрывает всю открытую вершину объектов —, ломаную линию, запись таблицы блоков, и таблицу блоков. Когда объект ломаной линии закрыт, AutoCAD добавляет объект AcDbSequenceEnd к этому автоматически.
    void
    createPolyline()
    {
    // Set four vertex locations for the pline.
    //
    AcGePoint3dArray ptArr;
    ptArr.setLogicalLength(4);
    for (int i = 0; i < 4; i++) {
    ptArr[i].set((double)(i/2), (double)(i%2), 0.0);
    }
    // Dynamically allocate an AcDb2dPolyline object,
    // given four vertex elements whose locations are supplied
    // in ptArr. The polyline has no elevation, and is
    // explicitly set as closed. The polyline is simple;
    // that is, not curve fit or a spline. By default, the
    // widths are all 0.0 and there are no bulge factors.
    //
    AcDb2dPolyline *pNewPline = new AcDb2dPolyline(
    AcDb::k2dSimplePoly, ptArr, 0.0, Adesk::kTrue);
    pNewPline->setColorIndex(3);
    // Get a pointer to a Block Table object.
    //
    AcDbBlockTable *pBlockTable;
    acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pBlockTable, AcDb::kForRead);
    // Get a pointer to the MODEL_SPACE BlockTableRecord.
    //
    AcDbBlockTableRecord *pBlockTableRecord;
    pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord,
    AcDb::kForWrite);
    pBlockTable->close();
    // Append the pline object to the database and
    // obtain its object ID.
    //
    AcDbObjectId plineObjId;
    pBlockTableRecord->appendAcDbEntity(plineObjId,
    pNewPline);
    pBlockTableRecord->close();
    // Make the pline object reside on layer "0".
    //
    pNewPline->setLayer("0");
    pNewPline->close();
    }

    Создание Заказных Классов

    Вы можете усиливать классы в иерархии ObjectARX, чтобы создать ваши собственные
    заказные классы. Кроме того, Вы можете использовать обширную графику
    Библиотеки ObjectARX при создании заказных классов.

    Вы можете получать заказные классы из большинства ObjectARX иерархии классов.
    Это позволяет Вам усиливать функциональные возможности классов ObjectARX при создании ваших собственных объектов. Определение заказных классов обсуждено подробно в гл. 11, "Получении Заказного ObjectARX Класса".

    Создание Заказных Режимов объектной привязки

    Заказные режимы объектной привязки позволяют разработчику устанавливать следующие атрибуты:
    § Ключевое слово
    Заказное объектное поспешное ключевое слово, что пользователь типы в, чтобы активизировать объектную привязку. И местные и глобальные ключевые слова должны быть определены.
    § класс расширения Протокола
    Указатель на класс, который исполняет обработку " в юридическое лицо " режима объектной привязки.
    § Глиф(Glyph)
    Заказной глиф для режима объектной привязки.
    § ToolTip строка
    По умолчанию ToolTip
    строка для заказного режима объектной привязки.
    Для подробной информации относительно установки этих атрибутов, см. ObjectARX Ссылку.
    Заказной режим объектной привязки определен,  регистрируя образец AcDbCustomOsnapMode класса с заказным объектным менеджером привязок, описан в предыдущей секции.
    Когда заказной режим объектной привязки используется, AutoCAD берет объект класса, возвращенный AcDbCustomOsnapMode:: entityOsnapClass (), взгляды соответствующий объект расширения протокола для выбранного примитива, и вызывает AcDbCustomOsnapInfo:: getOsnapInfo () чтобы получить точки или линии, связанные с тем примитивом и режимом объектной привязки. Если она кандидат, точка связана с тем режимом объектной привязки, AutoCAD, отображает объект глифа от образца, возвращенного AcDbCustomOsnapMode::gluph () и ToolTip строка, возвращенная AcDbCustomOsnapMode:: tooltipString ().

    Создание записи простой таблицы блока

    Следующий пример демонстрирует создание новой записи таблицы блоков и добавления ее в конец этой таблицы. Он создает линию и добавляет ее в новый блок.
    void
    makeABlock()
    {
    // Create and name a new block table record.
    //
    AcDbBlockTableRecord *pBlockTableRec
    = new AcDbBlockTableRecord();
    pBlockTableRec->setName("ASDK-NO-ATTR");
    // Get the block table.
    //
    AcDbBlockTable *pBlockTable = NULL;
    acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pBlockTable, AcDb::kForWrite);
    // Add the new block table record to the block table.
    //
    AcDbObjectId blockTableRecordId;
    pBlockTable->add(blockTableRecordId, pBlockTableRec);
    pBlockTable->close();
    // Create and add a line entity to the component’s
    // block record.
    //
    AcDbLine *pLine = new AcDbLine();
    AcDbObjectId lineId;
    pLine->setStartPoint(AcGePoint3d(3, 3, 0));
    pLine->setEndPoint(AcGePoint3d(6, 6, 0));
    pLine->setColorIndex(3);
    pBlockTableRec->appendAcDbEntity(lineId, pLine);
    pLine->close();
    pBlockTableRec->close();
    }

    Создание записи таблицы блоков с определениями атрибута

    Блок AutoCAD - коллекция примитивов, который сохранен в записи таблицы блоков. Каждый блок имеет объект AcDbBlockBegin, сопровождаемый одним или большее количество объектов AcDbEntity, и заканчивается объектом AcDbBlockEnd (см. иллюстрацию на странице 100).
    Блок может содержать определения атрибута, которые являются шаблонами для создания атрибутов. Атрибут - информационный текст, связанный с блоком. В зависимости от обеспеченной пользователем установки, атрибуты со значением могут или не может быть скопирован, когда блок вставлен в рисунок. Часто, приложение запрашивает пользователя относительно атрибута со значением во время выполнения.
    Создавать запись таблицы блоков
    1 Создают новую запись таблицы блоков.
    2 Добавляют запись таблицы блоков на таблицу блоков.
    3 Создают примитивы и добавляют их к записи таблицы блоков.
    4 Создают определения атрибута, устанавливают их значения, и добавляют их к записи таблицы блоков.
    Когда Вы закрываете запись таблицы блоков, блок начинает и блокирует конечные объекты,  добавлены к блоку автоматически.
    Следующий пример создает новую запись таблицы блоков по имени ASDK-BLOCK-WITH-ATTR и добавляет это к таблице блоков. Затем это создает примитив круга и добавляет это к новой записи таблицы блоков. Это создает два примитива определения атрибута (второй - аналог первых) и добавляет в конец их к той же самой записи таблицы блоков.
    void
    defineBlockWithAttributes(
    AcDbObjectId& blockId, // This is a returned value.
    const AcGePoint3d& basePoint,
    double textHeight,
    double textAngle)
    {
    int retCode = 0;
    AcDbBlockTable *pBlockTable = NULL;
    AcDbBlockTableRecord* pBlockRecord = new AcDbBlockTableRecord;
    AcDbObjectId entityId;
    // Step 1: Set the block name and base point of the
    // block definition.
    //
    pBlockRecord->setName("ASDK-BLOCK-WITH-ATTR");
    pBlockRecord->setOrigin(basePoint);
    // Open the block table for write.
    //
    acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pBlockTable, AcDb::kForWrite);

    // Step 2: Add the block table record to block table.

    //

    pBlockTable->add(blockId, pBlockRecord);

    // Step 3: Create a circle entity.

    //

    AcDbCircle *pCircle = new AcDbCircle;

    pCircle->setCenter(basePoint);

    pCircle->setRadius(textHeight * 4.0);

    pCircle->setColorIndex(3);

    // Append the circle entity to the block record.

    //

    pBlockRecord->appendAcDbEntity(entityId, pCircle);

    pCircle->close();

    // Step 4: Create an attribute definition entity.

    //

    AcDbAttributeDefinition *pAttdef

    = new AcDbAttributeDefinition;

    // Set the attribute definition values.

    //

    pAttdef->setPosition(basePoint);

    pAttdef->setHeight(textHeight);

    pAttdef->setRotation(textAngle);

    pAttdef->setHorizontalMode(AcDb::kTextLeft);

    pAttdef->setVerticalMode(AcDb::kTextBase);

    pAttdef->setPrompt("Prompt");

    pAttdef->setTextString("DEFAULT");

    pAttdef->setTag("Tag");

    pAttdef->setInvisible(Adesk::kFalse);

    pAttdef->setVerifiable(Adesk::kFalse);

    pAttdef->setPreset(Adesk::kFalse);

    pAttdef->setConstant(Adesk::kFalse);

    pAttdef->setFieldLength(25);

    // Append the attribute definition to the block.

    //

    pBlockRecord->appendAcDbEntity(entityId, pAttdef);

    // The second attribute definition is a little easier

    // because we are cloning the first one.

    //

    AcDbAttributeDefinition *pAttdef2

    = AcDbAttributeDefinition::cast(pAttdef->clone());

    // Set the values that are specific to the

    // second attribute definition.

    //

    AcGePoint3d tempPt(basePoint);

    tempPt.y -= pAttdef2->height();

    pAttdef2->setPosition(tempPt);

    pAttdef2->setColorIndex(1); // Red

    pAttdef2->setConstant(Adesk::kTrue);

    // Append the second attribute definition to the block.

    //

    pBlockRecord->appendAcDbEntity(entityId, pAttdef2);

    pAttdef->close();

    pAttdef2->close();

    pBlockRecord->close();

    pBlockTable->close();

    return;

    }

    Создавать обертку Автоматизации для заказного объекта или примитива

    1 Основанный ваш проект согласно шагам в “ Введение Файла Проекта ATL. ”
    2 В файле заголовка объекта COM, включите axtempl.h (главное ActiveX файл заголовка шаблона Автоматизации) и файл (ы) заголовка для ваших заказных объектов или примитивов.
    3 Изменяют образование из объекта COM или примитива,  удаляя IDISPATCHIMPL часть образования и заменяя это со следующим кодом:
    // Для заказного объекта.
    //
    public IAcadObjectDispatchImpl &CLSID_WrapperClass,IWrapperClass,
    &IID_IWrapperClass,&LIBID_LIBRARYLib>
    // For a custom entity.
    //
    public IAcadEntityDispatchImpl &CLSID_WrapperClass,IWrapperClass,
    &IID_IWrapperClass,&LIBID_LIBRARYLib>
    4 Добавляют следующие вхождения в COM_MAP:
    COM_INTERFACE_ENTRY(IAcadBaseObject)
    COM_INTERFACE_ENTRY(IAcadObject)
    COM_INTERFACE_ENTRY(IAcadEntity) // For an entity only.
    COM_INTERFACE_ENTRY(IRetrieveApplication)
    COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer) // Only
    // necessary to support events.
    5 Добавляют следующую требуемую перегрузку к заголовку file:
    // IAcadBaseObjectImpl
    //
    virtual HRESULT
    CreateNewObject(
    AcDbObjectId& objId,
    TCHAR* entryName,
    TCHAR* keyName);
    Эта абстрактная функция, определенная в IACADBASEOBJECTIMPL шаблоне должна быть перегружена, чтобы позволить Вам добавлять заданные по умолчанию объекты к базе данных.
    6 Осуществляют CreateNewObject () для любго объекта или определенного примитива.
    Следующий пример показывает выполнение CreateNewObject () из AsdkSquareWrapper:
    HRESULT CAsdkSquareWrapper::CreateNewObject(
    AcDbObjectId& objId,
    AcDbObjectId& ownerId,
    TCHAR* keyName)
    {
    try
    {
    //AXEntityDocLock(ownerId);
    Acad::ErrorStatus es;
    AcDbObjectPointer pSq;
    if((es = pSq.create()) != Acad::eOk)
    throw es;
    AcDbDatabase* pDb = ownerId.database();
    pSq->setDatabaseDefaults(pDb);
    AcDbBlockTableRecordPointer
    pBlockTableRecord(ownerId, AcDb::kForWrite);
    if((es = pBlockTableRecord.openStatus()) != Acad::eOk)

    throw es;

    if((es = pBlockTableRecord->appendAcDbEntity(objId, pSq.object())) != Acad::eOk)

    throw es;

    }

    catch(const Acad::ErrorStatus)

    {

    //To become more sophisticated

    //

    return Error(L"Failed to create square",

    IID_IAsdkSquareWrapper, E_FAIL);

    }

    return S_OK;

    }

    7 В файле IDL, добавьте importlib ("c:\ACAD\acad.tlb"); после importlib stdole32.tlb и importlib stdole2.tlb. Удостоверитесь, чтобы использовать правильный путь, который соответствует вашей инсталляции AutoCAD.

    8 Перемещают acad.tlb секцию в вершину файла IDL и перемещают ваш заказной объектный код так, чтобы это было в пределах той секции.

    ОБРАТИТЕ ВНИМАНИЕ, что  модификации файла IDL заставят компилятор выпускать предупреждение, заявляющее, что интерфейс не соответствует. Вы можете игнорировать это сообщение.

    9 Изменяют{*заменяют*} образование в файле IDL от IDISPATCH до IACADOBJECT для заказного объекта или IACADENTITY для заказного примитива.

    10 В секции файла IDL, который соответствует вашей обертке coclass, добавьте [источник] связывают с помощью интерфейса IACADOBJECTEVENTS; после [заданной по умолчанию] линии, чтобы поддерживать события. Файл IDL будет теперь казаться подобным следующему коду:

    import "oaidl.idl";

    import "ocidl.idl";

    [

    uuid(800F70A1-6DE9-11D2-A7A6-0060B0872457),

    version(1.0),

    helpstring("AsdkSquareLib 1.0 Type Library")

    ]

    library ASDKSQUARELIBLib

    {

    importlib("stdole32.tlb");

    importlib("stdole2.tlb");

    importlib("v:\acad\acad2000\acad.tlb");

    [

    object,

    uuid(800F70AD-6DE9-11D2-A7A6-0060B0872457),

    dual,

    helpstring("IAsdkSquareWrapper Interface"),

    pointer_default(unique)

    ]

    interface IAsdkSquareWrapper : IAcadEntity

    {

    [propget, id(1), helpstring("property Number")]

    HRESULT Number([out, retval] short *pVal);

    [propput, id(1), helpstring("property Number")]

    HRESULT Number([in] short newVal);

    };

    [

    uuid(800F70AE-6DE9-11D2-A7A6-0060B0872457),


    helpstring("AsdkSquareWrapper Class")

    ]

    coclass AsdkSquareWrapper

    {

    [default] interface IAsdkSquareWrapper;

    [source] interface IAcadObjectEvents;

    };

    };

    11 После #include в stdafx.h, включите acad15.h, сначала, сопровождаемый любыми необходимыми ObjectARX файлами заголовка.

    12 в конце stdafx.cpp, включите acad15_i.c.

    13, если приложение ARX и обертка COM объединено, добавьте следующий код к вашему главному CPP файл, и назовите это DllMain в AcRx:: kInitAppMsg и AcRx:: kUnloadAppMsg с соответствующими параметрами. Это инициализирует карту объекта ATL, среди других вещей:

    extern "C" HINSTANCE _hdllInstance;

    extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance,

    DWORD dwReason,LPVOID /*lpReserved*/);

    14 Добавляют желательные ActiveX методы, и свойства к вашему классу обертки выбором Добавляют Метод или Добавляют Свойство от подручного меню Интерфейса представления{*вида*} Класса.

    15 Для любого ObjectARX обертываемого класса, перегрузите getClassId () функция для заказного объекта или примитива со следующим:

    Acad::ErrorStatus

    Class::getClassID(CLSID* pClsid) const

    {

    *pClsid = CLSID_WrapperClass;

    return Acad::eOk;

    }

    16 В файле, который содержит,  перегрузка для getClassId (), добавляет:

    #include

    #include

    #include

    "library_i.c"            // Файл, содержащий фактические определения

    // IIDs

    и CLSIDS

    для проекта COM.

    17 Компоновки и регистр приложение согласно шагам в “ Формирование и Регистрация COM DLL. ”

    Специфические для приложения объекты документа

    Эта секция выделяет, как приложения MDI-Aware должны быть структурированы. Фактически все разработчики ObjectARX-приложения должны обслужить{*поддержать*} карту между поддерживаемыми системой объектами документа и передачей специфических для приложения данных. Любая такая карта должна быть манипулирована с определенными значениями указателя AcApDocument (адреса).
    Это требует, чтобы приложение по крайней мере осуществило повторные вызовы для AcApDocManagerReactor методов documentCreated () и documentToBeDestroyed (), создавать и удалять передачу docu-ment-specific состояние. Удостоверитесь, что ваши указатели AcApDocument современны, поскольку они будут вероятно многократно использоваться, поскольку документы закончены и созданы. Как альтернатива, Вы можете осуществлять обработчики для того, когда ваш acrxEntryPoint () функция вызвана с AcRx:: kLoadDwgMsg и AcRx:: kUnloadDwgMsg сообщения, которые вызваны с документом в вопросе, являющемся текущим.
    Такие специфические для приложения данные должны содержать любое состояние, которое должно быть связано с каждым открытым документом, который должен упорствовать{*сохраниться*} поперек команд. Одна альтернатива выполнения была бы должна обслужить{*поддержать*} AcArray шаблон класса, чей образцы состоят из указателя AcApDocument и указателя на, или образца, вашего документированного - определенного состояния, и чей == оператор перезагружен, чтобы сравнить только AcApDocument* члена. Другой подход был бы состоял в том, чтобы обслужить{*поддержать*} пару массивов с соответствующими элементами, делайте находку на указателях документа, и выберите соответствующий элемент из
    Другой массив.

    Специфичные для приложения Данные

    Ads_client_data_tile () функция назначает специфичные для приложения данные к полю ввода. Данные доступны при повторном вызове время как пакет повторного вызова client_data поле. Клиентские данные не представлены в DCL; это имеет силу только, в то время как ваше приложение выполняется. Использование клиентских данных сопоставимо использованию определяемых пользователем атрибутов. Основное различие - то, что определяемые пользователем атрибуты являются только для чтения, в то время как клиентские данные могут изменяться во время выполнения. (Также, конечные пользователи могут осматривать определяемые пользователем атрибуты в файле приложения DCL, но клиентские данные невидимы для них.)
    Клиентские данные могут иметь любой тип, который Вы выбираете. Это объявлено как указатель на пусто.
    Вы можете выражать клиентские данные как указатель на структуру данных, связанную с диалоговым окном или полем ввода. Структура может быть объявлена как временные данные, местные к любой функции в или выше уровня функции, которая вызывает ads_start_dialog (). Это позволяет Вам избегать объявлять клиентские данные как глобальные статические данные.
    Клиентские данные - полезный способ передать информацию к функции повторного вызова, потому что никакие дополнительные параметры не могут быть добавлены к функции.
    Поскольку ваша программа должна поддержать список, отображенный списком (или всплывающий список), клиентские данные хороши для обработки этой информации. Предыдущий пример mk_list () функция уже заставит список оценить параметр.
    Это - тип указателя, который предоставляет себя, чтобы использовать как клиентские данные. Например, основная функция, чтобы обработать то же самое диалоговое окно могла включать следующий код (проверка ошибок минимизирована для простоты):
    struct resbuf *usrhead;
    int
    handler()
    {
    struct resbuf *csyshead, *usrhead;
    ads_hdlg cldlg;
    if (ads_new_dialog("clistdlg", dcl_id, NULLCB, &cldlg))
    return BAD;
    csyshead = acutBuildList(RTSTR, "Red-Green-Blue",
    RTSTR, "Cyan-Magenta-Yellow",
    RTSTR, "Hue-Saturation-Value", 0);
    if (csyshead == NULL)
    return BAD;
    ads_client_data_tile(cldlg, "colorsyslist", csyshead);
    ads_action_tile(cldlg, "colorsyslist", listcallback);
    ...
    // Start dialog box and do other processing.
    //
    ...
    }
    Затем, функция повторного вызова listcallback () вызывает mk_list () следующим образом:
    static void CALLB
    listcallback(ads_callback_packet *cpkt)
    {
    if ((cpkt->reason == CBR_SELECT) || (cpkt->reason == CBR_DOUBLE_CLICK)) {
    // This is not the default tile, so treat both the same.
    //
    usrhead = mk_list(cpkt->value, cpkt->client_data);
    }
    }

    Спецификации Ключевого слова

    Необязательный kwl параметр определяет список ключевых слов, которые будут признаны следующим вводом пользователя (acedGetxxx ()) функциональный запрос. Значение ключевого слова, которое пользователь вводит, может быть восстановлено{*отыскано*} последующим запросом к acedGetInput () (. Значение ключевого слова было бы доступно, если функция ввода пользователя была acedGetKword ().) значения ключевых слов и действия, чтобы исполнить для каждого - ответственность ObjectARX-приложения.
    AcedGetInput () функция всегда возвращает ключевое слово, поскольку это появляется в kwl параметре, с тем же самым преобразованием букв в прописные (но не с необязательными символами, если те определены после запятой). Независимо от того, как пользователь вводит ключевое слово, приложение должно делать только одно строковое сравнение, чтобы идентифицировать это, как демонстрируется в следующем примере. Доля кода, которая следует за показами запрос к acedGetReal () предшеств запросом к acedInitGet () который определяет два ключевых слова. Приложение проверяет эти ключевые слова и устанавливает входное значение соответственно.
    int stat;
    ads_real x, pi = 3.14159265;
    char kw[20];
    // Null input is not allowed.
    acedInitGet(RSG_NONULL, "Pi Two-pi");
    if ((stat = acedGetReal("Pi/Two-pi/: ", &x)) < 0) {
    if (stat == RTKWORD && acedGetInput(kw) == RTNORM) {
    if (strcmp(kw, "Pi") == 0) {
    x = pi;
    stat = RTNORM;
    } else if (strcmp(kw, "Two-pi") == 0) {
    x = pi * 2;
    stat = RTNORM;
    }
    }
    }
    if (stat != RTNORM)
    acutPrintf("Error on acedGetReal() input.\n");
    else
    acutPrintf("You entered %f\n", x);
    Запрос к acedInitGet () предотвращает пустой указатель, вводят, и определяет два ключевых слова: “Pi” и “Два - pi”. Когда acedGetReal () вызван{*назван*}, пользователь отвечает на подсказку Pi/Two-pi / <номеру>,  вводя или реальное значение (сохраненный в местной переменной x) или одном из ключевых слов. Если пользователь вводит ключевое слово, acedGetReal () возвращает RTKWORD. Приложение отыскивает ключевое слово,  вызывая acedGetInput () (обратите внимание, что это проверяет{*отмечает*} состояние ошибки этой функции), и затем устанавливает значение x к pi или 2pi, в зависимости от которого ключевое слово было введено. В этом примере, пользователь может вводить или p, чтобы выбрать pi или t, чтобы выбрать 2pi.

    Списки AutoLISP

    AcutBuildList() функция вызвана в сочетании и с acedRetList(), который возвращает структуру списка AutoLISP.
    Следующий типовой кодовый фрагмент передает список четырех точек:
    struct resbuf *res_list;
    ads_point ptarray[4];
    // Initialize the point values here.
    .
    .
    .
    res_list = acutBuildList(
    RT3DPOINT, ptarray[0],
    RT3DPOINT, ptarray[1],
    RT3DPOINT, ptarray[2],
    RT3DPOINT, ptarray[3], 0);
    if (res_list == NULL) {
    acdbFail("Couldn’t create list\n");
    return BAD;
    }
    acedRetList(res_list);
    acutRelRb(res_list);
    Точечные пары и вложенные списки могут быть возвращены AutoLISP,  вызывая acutBuildList () чтобы формировать список, созданный со специальными кодами типа строительства списка. Эти коды необходимы только для сложных списков. Для обычного (то есть одномерный) списки, acedRetList () можно пропускать простой список буферов результатов, как показано в предыдущем примере.
    ОБРАТИТЕ ВНИМАНИЕ список, возвращенный AutoLISP acedRetList () может включать только следующие коды типа результата: RTREAL, RTPOINT, RTSHORT, RTANG, RTSTR, RTENAME, RTPICKS, RTORINT, RT3DPOINT, RTLB, RTLE, RTDOTE, RTNIL, и RTT. (Хотя имеется RTNIL код возврата, если Вы возвращаете только список ноля, Вы можете вызывать acedRetNil ()). Это может содержать типы результата RTLONG, если список возвращается другому ObjectARX-приложению.
    Использование кодов типа строительства списка просто. В acutBuildList () запросу, вложенный список предшествует тип результата, закодируют RTLB (для Списка, начинают) и сопровождается типом результата, закодируют RTLE (для Списка Конец). Точечная пара может также быть создана. Точечные пары также начинаются с RTLB и конца с RTLE; точка обозначена типом результата, закодируют RTDOTE, и появляется между двумя членами пары.
    ПРИМЕЧАНИЕ Это – изменение от более ранних версий. Приложения, которые не получают точечную пару от AutoLISP больше, должны изменить формат точечной пары перед возвращением этого с acedRetList () (. Более ранний порядок, с RTDOTE в конец, все еще поддерживается.)

    ПРЕДУПРЕЖДЕНИЕ! AcutBuildList () функция не проверяет правильно построенный список AutoLISP. Например, если RTLB и коды RTLE не сбалансированы, эта ошибка не обнаружена. Если список хорошо не сформирован, AutoLISP может терпеть неудачу. Исключение кода RTLE, как гарантируют,  будет фатальной ошибкой.

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

    res_list = acutBuildList(

    RTLB, // Begin sublist.

    RTSHORT, 1,

    RTSHORT, 2,

    RTSHORT, 3,

    RTLE, // End sublist.

    RTSHORT, 4,

    RTSHORT, 5,

    0);

    if (res_list == NULL) {

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

    return BAD;

    }

    acedRetList(res_list);

    acutRelRb(res_list);

    The list that this example returns to AutoLISP has the following form:

    ((1 2 3) 4 5)

    The following code fragment constructs a dotted pair to return to AutoLISP:

    res_list = acutBuildList(

    RTLB, // Begin dotted pair.

    RTSTR, "Sample",

    RTDOTE,

    RTSTR, "Strings",

    RTLE, // End dotted pair.

    0);

    if (res_list == NULL) {

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

    return BAD;

    }

    acedRetList(res_list);

    acutRelRb(res_list);

    Список, который этот пример возвращается AutoLISP, имеет следующую форму:

    ((“Sample” . “Strings”))

    ОБРАТИТЕ ВНИМАНИЕ В AutoLISP, кодах группы DXF связери точечных пар и значениях. В ObjectARX-приложении это ненужно, потому что единственный{*отдельный*} буфер результатов содержит, и код группы (в его restype поле) и значении (в его resval поле). В то время как ObjectARX обеспечивает коды типа строительства списка как удобство, большинство ObjectARX-приложений не требует их.

    Списки Фильтра Набора Выбора

    Когда entmask параметр определяет, что список значений поля примитива, acedSSGet () просматривает выбранные примитивы и создает набор выборов, содержащий названия{*имена*} всех основных примитивов, которые соответствуют{*согласовывают*} указанным критериям. Например, используя этот механизм, Вы можете получить набор выборов, который включает все примитивы данного типа, на данном уровне, или данного цвета.
    Вы можете использовать фильтр вместе с любой из опций выбора. Опция “X” говорит, что создала набор выборов, используя только фильтрация; как в предыдущих версиях AutoCAD, если Вы используете,  опция “X”, acedSSGet () просматривает полную базу данных рисунка.
    ОБРАТИТЕ ВНИМАНИЕ, определена ли только фильтрация (“X”) но entmask параметр - NULL, acedSSGet () выбирает все примитивы в базе данных.
    Entmask параметр должен быть список буфера результата. Каждый буфер определяет свойство, чтобы проверить{*отметить*} и значение, которое составляет соответствие; restype поле буфера - код группы DXF, который указывает вид свойства, чтобы смотреть для, и его resval поле определяет значение, чтобы соответствовать{*согласовать*}.
    Следующее - некоторые примеры.
    struct resbuf eb1, eb2, eb3;
    char sbuf1[10], sbuf2[10]; // Buffers to hold strings
    ads_name ssname1, ssname2;
    eb1.restype = 0;// Entity name
    strcpy(sbuf1, "CIRCLE");
    eb1.resval.rstring = sbuf1;
    eb1.rbnext = NULL; // No other properties
    // Retrieve all circles.
    acedSSGet("X", NULL, NULL, &eb1, ssname1);
    eb2.restype = 8; // Layer name
    strcpy(sbuf2, "FLOOR3");
    eb2.resval.rstring = sbuf2;
    eb2.rbnext = NULL; // No other properties
    // Retrieve all entities on layer FLOOR3.
    acedSSGet("X", NULL, NULL, &eb2, ssname2);
    ОБРАТИТЕ ВНИМАНИЕ resval, указанный в каждом буфере должен иметь соответствующий тип.
    Например, типы имени - строки (resval.rstring); повышение и толщина - с двойной точностью с плавающей точкой значения (resval.rreal); цвет, признаки - следуйте, и пометьте значения - короткие целые числа (resval.rint); векторы вытеснения - трехмерные точки (resval.rpoint); и т.д.

    Если entmask определяет больше чем одно свойство, примитив включен в выбор, устанавливают только, если это соответствует всем указанным условиям{*состояниям*}, как показано в следующем примере:

    eb3.restype = 62; // Entity color

    eb3.resval.rint = 1; // Request red entities.

    eb3.rbnext = NULL; // Last property in list

    eb1.rbnext = &eb2; // Add the two properties

    eb2.rbnext = &eb3; // to form a list.

    // Retrieve all red circles on layer FLOOR3.

    acedSSGet("X", NULL, NULL, &eb1, ssname1);

    Примитив проверен против всех полей, указанных в списке фильтрации, если список не содержит относительные или условные операторы, как описано в “ Относительные Испытания ” на странице 207 и “ Фильтрация Условного выражения ” на странице 208.

    AcedSSGet () функциональные возвращения RTERROR, если никакие примитивы в базе данных не соответствуют{*согласовывают*} указанным критериям фильтрации.

    Предыдущий acedSSGet () примеры используют опцию “X”, которая просматривает полную базу данных рисунка. Если списки фильтра используются вместе с другими опциями (выбор пользователя, окно, и т.д), фильтр применяется только к примитивам, первоначально выбранным.

    Следующее - пример фильтрации выбранных пользователем примитивов.

    eb1.restype = 0; // Entity type group

    strcpy(sbuf1, "TEXT");

    eb1.resval.rstring = sbuf1; // Entity type is text.

    eb1.rbnext = NULL;

    // Ask the user to generally select entities, but include

    // only text entities in the selection set returned.

    acedSSGet(NULL, NULL, NULL, &eb1, ssname1);

    Следующий пример демонстрирует фильтрацию предыдущего набора выборов.

    eb1.restype = 0; // Entity type group

    strcpy(sbuf1, "LINE");

    eb1.resval.rstring = sbuf1; // Entity type is line.

    eb1.rbnext = NULL;

    // Select all the lines in the previously created selection set.

    acedSSGet("P", NULL, NULL, &eb1, ssname1);

    eb1.restype = 8; // Layer

    strcpy(sbuf1, "FLOOR9");

    eb1.resval.rstring = sbuf1; // Layer name

    eb1.rbnext = NULL;

    // Select all the entities within the window that are also on the layer FLOOR9.

    acedSSGet("W", pt1, pt2, &eb1, ssname1);

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



    Списки и другие динамически размещенные данные

    Структура resbuf включает поле указателя, rbnext, для соединения буферов результатов в список. Буфера Результатов могут быть размещены статически,  объявляя их в приложении. Вы делаете это, когда только единственный буфер результатов используется (например, acedGetVar () и acedSetVar ()) или когда, только короткий список необходим. Но более длинные списки проще, чтобы обработать,  размещая их динамически, и списки, возвращенные функциями ObjectARX всегда размещаются динамически. Один из наиболее часто используемые функции, который возвращает список связей - acedGetArgs ().
    “ Оценка Внешних Функций ” на странице 526 показывает AutoLISP, запрашивающий  внешней подпрограммы, которая берет параметры трех отличных типов: строка, целое число, и реальное значение:
    ( Doit pstr iarg rarg)
    Следующий код сегментирует показы, как осуществить функцию с такой последовательностью запроса. Типовая функция проверяет, чтобы список параметров был правилен и сохранил значения в местном масштабе перед действием на них (операции не показываются). Пример предполагает, что предыдущий запрос к acedDefun () назначил внешнюю подпрограмму функциональный код 0, и что все функции, определенные этим приложением берут по крайней мере один параметр:
    // Выполнить определенную функцию.
    int dofun()
    {
    struct resbuf *rb;
    char str[64];
    int ival, val;
    ads_real rval;
    ads_point pt;
    // Get the function code.
    if ((val = acedGetFuncode()) == RTERROR)
    return BAD; // Indicate failure.
    // Get the arguments passed in with the function.
    if ((rb = acedGetArgs()) == NULL)
    return BAD;
    switch (val) { // Which function is called?
    case 0: // (doit)
    if (rb->restype != RTSTR) {
    acutPrintf("\nDOIT called with %d type.", rb->restype);
    acutPrintf("\nExpected a string.");
    return BAD;
    }
    // Save the value in local string.
    strcpy(str, rb->resval.rstring);
    // Advance to the next result buffer.
    rb = rb->rbnext;
    if (rb == NULL) {
    acutPrintf("\nDOIT: Insufficient number of arguments.");

    return BAD;

    }

    if (rb->restype != RTSHORT) {

    acutPrintf("\nDOIT called with %d type.", rb->restype);

    acutPrintf("\nExpected a short integer.");

    return BAD;

    }

    // Save the value in local variable.

    ival = rb->resval.rint;

    // Advance to the last argument.

    rb = rb->rbnext;

    if (rb == NULL) {

    acutPrintf("\nDOIT: Insufficient number of arguments.");

    return BAD;

    }

    if (rb->restype != RTREAL) {

    acutPrintf("\nDOIT called with %d type.", rb->restype);

    acutPrintf("\nExpected a real.");

    return BAD;

    }

    // Save the value in local variable.

    rval = rb->resval.rreal;

    // Check that it was the last argument.

    if (rb->rbnext != NULL) {

    acutPrintf("\nDOIT: Too many arguments.");

    return BAD;

    }

    // Operate on the three arguments.

    . . .

    return GOOD; // Indicate success

    break;

    case 1:

    // Execute other functions.

    . . .

    }

    }

    ОБРАТИТЕ ВНИМАНИЕ, что этот пример исключителен в одном отношении: acedGetArgs () - единственная ObjectARX глобальная функция, которая возвращает список связей, который приложение должно явно не выпустить. Следующая секция описывает обычный путь управления памятью, необходимой для списков.

    Списки Примитива с Кодами DXF в ObjectARX

    Как предварительно упомянуто, списки с кодами группы DXF представляют примитивы AutoCAD. AcutBuildList() функция создает такие списки. Чтобы создавать примитив, вызовите, и acutBuildList () и acdbEntMake ().
    ОБРАТИТЕ ВНИМАНИЕ, что определения Примитива начинают с нуля (0) группы, которая описывает тип примитива. Поскольку списки прошли к acutBuildList () закончены с 0 (или RTNONE), это создает конфликт. Специальный тип результата закодирует RTDXF0, решает конфликт. Создайте нулевую группу в списках DXF, пропускал к acutBuildList () с RTDXF0. Если Вы пытаетесь заменять литеральный нуль на RTDXF0, acutBuildList () усекает список.
    Следующий типовой кодовый фрагмент создает список DXF, который описывает круг и затем передает новый примитив к acdbEntMake (). Круг центрирован в (4,4), имеет радиус 1, и окрашен красным:
    struct resbuf *newent;
    ads_point center = {4.0, 4.0, 0.0};
    newent = acutBuildList(
    RTDXF0, "CIRCLE",
    62, 1, // 1 == red
    10, center,
    40, 1.0, // Radius
    0 );
    if (acdbEntMake(newent) != RTNORM) {
    acdbFail("Error making circle entity\n");
    return BAD;
    }

    Список Ключевого слова

    Если Вы имеете ключевые слова, которые являются значимыми в перетащенной последовательности, используют следующую функцию, чтобы определить их:
    void
    AcEdJig::setKeywordList(const char* kyWdList);
     Список ключевого слова - одиночная строка, в которой каждое ключевое слово отделено от другие пробелами. Требуемые символы напечатаны прописными буквами, и остаток от каждого ключевого слова - нижний регистр.
    Например, “Close Undo ”, определяет два ключевых слова. DragStatus перечислимые партнеры оценивают с каждым ключевым словом. Первое ключевое слово - kKW1, второй - kKW2, и так далее. Когда Вы осуществляете ваш AcEdJig класс, Вы можете использовать эти возвращаемые значения в ваших выполнении sampler(), update(), и entity() функции.

    Иерархия классов для таблиц идентификаторов,

    Иерархия классов для таблиц идентификаторов, записей таблицы идентификаторов, словарей, и iterators следующие.

    Иерархия классов для таблиц идентификаторов,

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

    Эти записи могут быть стерты только с командой PURGE или выборочно фильтрован из с wblock

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

    ПРЕДУПРЕЖДЕНИЕ! Стирание словарей или входов словаря (см. “ Обязательные Объекты Базы данных ” на странице 22) вероятно,  заставит AutoCAD или другие приложения терпеть неудачу.

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

    Symbol Table

                   -------> Symbol table record 

    Dictionary         ------->  Object

    Сравнение Таблиц идентификаторов и Словарей

    Таблицы идентификаторов и словари исполняют по существу ту же самую функцию; они содержат входы, которые являются базой данных, возражает, что можно искать, используя текстовую строковую клавишу{*ключ*}. Вы можете добавлять входы к этим контейнерным объектам, и Вы можете использовать iterator, чтобы шагнуть через входы и сделать запрос их содержания.
    База данных AutoCAD всегда содержит установленный набор девяти таблиц идентификаторов, описанных в следующем разделе. Вы не можете создавать или удалять таблицу идентификаторов, но Вы можете добавлять или изменять{*заменять*} входы в таблице идентификаторов, которые вызваны{*названы*} записи. Каждая таблица идентификаторов содержит только специфический тип объекта.
    Например, AcDbLayerTable содержит только объекты типа AcDbLayerTableRecord. Таблицы идентификаторов определены этим способом главным образом для совместимости с Выпуском AutoCAD 12 и предыдущих выпусков AutoCAD.
    Словари обеспечивают подобный механизм для сохранения и восстановления{*поиска*} объектов со связанными клавишами{*ключами*} имени. База данных AutoCAD создает названный объектный словарь всякий раз, когда это создает новый рисунок. Названный объектный словарь может рассматриваться как главное “оглавление” для структур объекта небытия в рисунке. Этот словарь, по умолчанию, содержит четыре словаря: словарь ГРУППЫ, MLINE
    словарь стиля, словарь размещения, и графический стиль называет словарь. Вы можете создавать любое число дополнительных объектов и добавлять их к названному объектному словарю. Однако, лучшая практика должна добавить один объект непосредственно к названному объектному словарю и иметь тот объект, в свою очередь имеют другие объекты, связанные с вашим приложением. Как правило, объект обладания - контейнерный класс типа словаря. Используйте ваш назначенный Зарегистрированный Символ Разработчика с четырьмя символами для имени этого класса.
    Объект AcDbDictionary может содержать любой тип AcDbObject, включая другие словари. Объект словаря не исполняет контроль соответствия типов входов. Однако, MLINE словарь стиля должен содержать только образцы класса AcDbMlineStyle, и словарь ГРУППЫ должен содержать только образцы AcDbGroup. Приложение может требовать определенного печатания для входов в словаре, который это создает и обслуживает{*поддерживает*}.

    Среда программирования ObjectARX

    ObjectARX среда программирования обеспечивает объектно-ориентированный C++
    прикладной программный интерфейс для разработчиков, чтобы использовать, настроить, и расширить AutoCAD. ObjectARX библиотеки включают непостоянный набор инструментальных средств для прикладных разработчиков, чтобы воспользоваться преимуществом открытой архитектуры AutoCAD, обеспечивая прямой доступ к структурам базы данных AutoCAD, графической системе, и коренным определениям команд. Кроме того, эти библиотеки разработаны с возможностью интерфейса с VLisp
    и другим прикладным языкам программирования так, чтобы разработчики могли выбирать инструментальные средства программирования.
    Как разработчик, Вы можете использовать ObjectARX, чтобы выполнить следующие задачи:
    · Обращение к базе данных AutoCAD
    · Взаимодействие с редактором AutoCAD
    · Создание интерфейса пользователя, использующее MFC
    · Поддержка многодокументной среды
    · Создание заказных классов
    · Формирование комплексного приложения
    · Взаимодействуют с другими средами программирования
    Этот раздел - краткий обзор этих тем. Более подробно они будут обсуждены в последующих разделах.

    Средство управления Ввода Пользователя

    Используйте следующую функцию, чтобы изменить средство управления ввода гипотетического пользователя:
    void setUserInputControls(AcEdJig::UserInputControls uic);
     Ввод пользователя управляет помещенными ограничениями на перетащенную последовательность или тип приемлемого возвращаемого значения (например, не позволяя отрицательные ответы, не позволяя нулевой ответ, или,  ограничивая входное значение к двумерной координате).
    Они также определяют, как различные действия пользователя затрагивают перетащенную последовательность.
    Например, kAcceptMouseUpAsPoint определяет, что выпуск кнопки мыши указывает входное значение.
    Средство управления ввода пользователя может быть одно из следующих значений:
    § kGovernedByOrthoMode
    § kNullResponseAccepted
    § kDontEchoCancelForCtrlC
    § kDontUpdateLastPoint
    § kNoDwgLimitsChecking
    § kNoZeroResponseAccepted
    § kNoNegativeResponseAccepted
    § kAccept3dCoordinates
    § kAcceptMouseUpAsPoint
    § kAnyBlankTerminatesInput
    § kInitialBlankTerminatesInput
    Как только Вы установили список ключевого слова, тип курсора, и средство управления ввода пользователя, ваш sampler() функция должна вызвать одну из следующих функций AcEdJig, чтобы получить угол, расстояние, или точку:
    DragStatus
    AcEdJig::acquireAngle(double &ang);
    DragStatus
    AcEdJig::acquireAngle(
    double &ang,
    const AcGePoint3d &basePt);
    DragStatus
    AcEdJig::acquireDist(double &dist);
    DragStatus
    AcEdJig::acquireDist(
    double &dist,
    const AcGePoint3d &basePt);
    DragStatus
    AcEdJig::acquirePoint(AcGePoint3d &point);
    DragStatus
    AcEdJig::acquirePoint(
    AcGePoint3d &point,
    const AcGePoint3d &basePt);
    После вызова sampler() функция, Вы можете исполнять любой дальнейший анализ на полученном геометрическом значении и перетаскивать состояние. Вы будете также хотеть кэшировать возвращаемое значение в статической переменной для доступа в вашей update() или entity() функции.
    § update() функция - типично, где Вы изменяете объект, обычно,  применяя преобразование к исходному объекту.
    § entity() функция возвращает указатель на объект, который будет восстановлен.

    Ссылки Монопольного использования (Ownership References)

    Если Вы создаете вашу собственную иерархию монопольных использований, Вы должны установить подключение{*связь*} между владельцем и находящимся в собственности объектом. Объект не может иметь множественных владельцев.
    Создавать подключение{*связь*} монопольного использования
    1 Определяют, что владелец имеет объект.
    2 Определяют, что объект принадлежит владельцу.
    AcDbObject протокол всегда определяет связь{*ссылку*} от владельца к находящемуся в собственности объекту и обратной связи{*ссылке*} от объекта до его владельца.
    Следующий код иллюстрирует установку двухсторонней связи{*ссылки*} монопольных использований между владельцем и ее содержанием:
    // Uses the OwnerDemo class defined in the next example
    // (see "ObjectARX Example," below).
    //
    // Sets pOwner to be the owner of pOwned.
    //
    void
    makeOwner(OwnerDemo* pOwner, AcDbObject* pOwned)
    {
    // First let pOwner know it is the owner. This
    // establishes ownership for filing persistence.
    //
    pOwner->setIdData(pOwned->ojectId());
    // Now set up the backpointer so that the owned
    // object knows who its owner is.
    //
    pOwned->setOwnerId(pOwner->objectId());
    }
    Обычно используемые члены контейнерного класса устанавливают двухстороннюю связь{*ссылку*} автоматически. Например, следующий функциональный запрос устанавливает блочный отчет{*запись*} таблицы как владелец объекта, и также прибавляет объект к блочному списку отчета{*записи*} таблицы находящихся в собственности объектов.
    BlockTableRecord- > appendAcDbEntity (...);
    Точно так же AcDbDictionary:: setAt () функция и AcDbSymbolTable:: добавляется () функция устанавливает двухсторонние связи{*ссылки*} между владельцем и ее объектами в одном шаге.
    Если Вы непосредственно управляете объектами, использующими entmod () или entmake () в AutoLISP, Вы сначала прибавляете находящийся в собственности объект к базе данных, используя entmake (), то присоединяете ее ads_name или название{*имя*} объекта с соответствующим кодом группы DXF в представлении объекта владельца.

    Стадия Трансляции

    И для глубокого клона и wblock
    клонируют функции, объекты, которые упомянуты первичным объектом,  также оттранслированы. После того, как объекты скопированы, AutoCAD транслирует ссылки как описано в следующем три случая.
    §
    Случай 1: Если упомянутый объект был скопирован, старая ссылка оттранслирована, чтобы обратиться{*отнестись*} к скопированному объекту. В этом случае, это не имеет значение, если скопированный объект находится в той же самой базе данных как исходные объекты или в новой базе данных.
    § Случай 2: Этот случай предполагает, что исходный объект и скопированный объект постоянно находятся в той же самой базе данных. Если упомянутый объект не был скопирован, ссылка оставлена на месте
    § Случай 3: Этот случай предполагает, что исходный объект и скопированный объект находятся в различных базах данных. Если упомянутый объект не был скопирован, ссылка к этому установлена в NULL (потому что это не находится в базе данных адресата).

    Как пример Случая 1, предположите, что Вы имеете Примитив 1, который содержит ссылку указателя к Примитиву B1. И Примитив 1 и Примитив B1 отобран, чтобы клонироваться. Перед трансляцией, Примитив 2 все еще относится к Примитиву B1. После трансляции, Примитив 2 модифицирован, чтобы отнестись к Примитиву B2.

    Стадия Трансляции


    Как пример Случая 2, предположите, что Вы имеете те же самые два примитива: Примитив 1 содержит ссылку указателя к Примитиву B1. Примитив 1 клонировался, но Примитив B1 - нет. Источник и адресат (клон), объекты находятся в той же самой базе данных.

    Стадия Трансляции


    Случай 3 подобен Случаю 2, кроме клонированных объектов находятся в новой базе данных. В этом случае, ссылка указателя Примитива 2 установлена в NULL, потому что Примитив B1 не в новой базе данных.

    Стадия Трансляции

    Статические OPM Интерфейсы COM

    Если заказной объект не осуществляет обертку объекта COM для себя, GetIUnknownOfObject генерирует заданную по умолчанию обертку, которая осуществляет методы IACADENTITY или IACADOBJECT, в зависимости от того, если основной объект может приводиться AcDbEntity. OPM тогда использует этот объект, чтобы отобразить Цвет, Уровень, Linetype, и Lineweight свойства, также известный как примитив общие свойства. ICategorizeProperties, IPerPropertyBrowsing, и IOPMPROPERTYEXTENSION - интерфейсы flavoring.
    Эта секция описывает OPM flavoring
    интерфейсы подробно и объясняет, как использовать их, чтобы управлять дисплей статических свойств в OPM.
    Все другие статические интерфейсы будут зарегистрированы в другом месте как часть документации Автоматизации.

    Стек Команды

    Команды AutoCAD сохранены в группах в стеке команды, который
    Определенный AcEdCommandStack классом. Один образец стека команды
    Создан в сеанс AutoCAD. Этот стек состоит из заказных команд
    То, что Вы определили. AcedRegCmds () макрокоманда дает Вам, обращаются к
    Стек команды.
    Когда Вы прибавляете команду, Вы также назначаете это название{*имя*} группы. Хорошая политика{*полис*}
    Должен использовать ваш буферизованный префикс разработчика для названия{*имени*} группы, чтобы избежать названия{*имени*}
    Столкновения с другими командами. Команда называет в пределах данной группы
    Должен быть уникален, и названия{*имена*} группы должны быть уникальны. Однако, множественные приложения
    Может прибавлять команду того же самого названия{*имени*}, потому что группа называет Делает команды однозначными.
    ОБРАТИТЕ ВНИМАНИЕ, что автоплата поддерживает схему регистрации разработчика предотвратить Namespace
    находится в противоречии между различными приложениями. Каждый буферизованный разработчик Выбирает одни или более буферизованные символы разработчика (RDS), чтобы использовать исключительно. Буферизованный Символы разработчика - одно из требований “ Сформированные с ObjectARX ” программа эмблемы. Для получения дополнительной информации, идите интерактивно к  http://www.veritest.com/autodesk/main(f).htm.
    Вы обычно прибавляете команды по одному с AcEdCommandStack:: addCommand () функция, и Вы удаляете команды Группа с AcEdCommandStack:: removeGroup () функция. Вы можете также Используйте AcEdCommandStack:: removeCmd () функция, чтобы удалить команды По одному. Как часть его очистки перед выходом, ваше приложение нуждается к Удалите любые команды это буферизованный.
    Сигнатура для addCommand () функция
    Acad::ErrorStatus
    addCommand(
    const char* cmdGroupName,
    const char* cmdGlobalName,
    const char* cmdLocalName,
    Adesk::Int32 commandFlags,
    AcRxFunctionPtr functionAddr,
    AcEdUIContext *UIContext=NULL,
    int fcode=-1,
    HINSTANCE hResourceHandle=NULL);

    CmdGroupName

    Представление ASCII группы, чтобы прибавить команду к.

    Если группа не существует, это создано прежде, чем команда добавлена.

    CmdGlobalName

    Представление ASCII команды называет, чтобы добавиться. Это название{*имя*} представляет глобальное или неоттранслированное название{*имя*} (см. “ Глобальная переменная против Местных Названий{*имен*} Команды ” на странице 42).

    CmdLocalName

    Представление ASCII команды называет, чтобы добавиться. Это название{*имя*} представляет местное или оттранслированное название{*имя*}.

    CommandFlags

    Флажки, связанные с командой. Возможные значения - ACRX_CMD_TRANSPARENT, ACRX_CMD_MODAL, ACRX_CMD_USEPICKSET, и ACRX_CMD_REDRAW (см. “ Прозрачный против Модальных Команд ” на странице 42).

    FunctionAddr

    Адрес функции, которая будет выполнена, когда эта команда вызвана в соответствии с AutoCAD.

    UiContext

    Входной указатель на AcEdUIContext класс повторного вызова.

    Fcode

    Введите целочисленный код, назначенный на команду.

    ПРИМЕЧАНИЕ, которое строго рекомендует, чтобы все имена команд имели Ваш зарегистрированный префикс разработчика с четырьмя символами, чтобы избежать возможных конфликтов с командами  в других приложениях. Например, MOVE команда  разработчика с префиксом ASDK

    должна быть ASDKMOVE.

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

    Сигнатура для removeCmd()

    virtual Acad::ErrorStatus

    AcEdCommandStack::removeCmd

    (const char* cmdGroupName,

    const char* cmdGlobalName) = 0;

    Сигнатура для removeGroup()

    virtual Acad::ErrorStatus

    AcEdCommandStack::removeGroup

    (const char* groupName);

    Стирание объекта

    Любой объект в базе данных может быть стерт следующей функцией:
    Acad::ErrorStatus
    AcDbObject::erase(Adesk::Boolean Erasing = Adesk::kTrue);
    ОБРАТИТЕ ВНИМАНИЕ  Erase() имеет различные результаты для объектов базы данных и примитивов, с последствиями для нестирания их:
    § когда объект базы данных стерт, информация относительно того объекта удалена из словаря. Если объект нестерт со стиранием (kfalse), информация автоматически не повторно представлена. Вы Должен использовать setAt () функция, чтобы прибавить информацию к словарю снова.
    § когда объект стерт, это просто помечено как стерто в блочном отчете{*записи*} таблицы. Объект может быть нестерт со стиранием (kfalse).
    По умолчанию, Вы не можете открывать стертый объект с acdbOpenObject () функция. Если Вы пытаетесь делать так, eWasErased код ошибки будет возвращен.
    extern Acad::ErrorStatus
    acdbOpenObject(AcDbObject*& obj,
    AcDbObjectId objId,
    AcDb::OpenMode openMode,
    Adesk::Boolean openErasedObject =
    Adesk::kFalse);
    Чтобы открывать стертый объект, используйте kTrue для последнего{*прошлого*} параметра acdbOpenObject () функция.
    Контейнерные объекты типа ломаных линий и блочных отчетов{*записей*} таблицы обычно обеспечивают опцию пропуска стертых элементов при выполнении итераций по их содержанию.
    Заданное по умолчанию поведение должно пропустить стертые элементы.
    Стертые объекты не зарегистрированы из к DWG или DXF файлам.

    Строковые Преобразования

    Функции acdbRToS () и acdbAngToS () преобразовывают значения, используемые в AutoCAD к строковым значениям, которые могут использоваться в выводе или как текстовые данные. AcdbRToS () функция преобразовывает реальное значение, и acdbAngToS () преобразовывает угол. Формат строки результата управляется значением переменных системы AutoCAD: модули и точность определены LUNITS и LUPREC для реальных (линейных) значений и AUNITS и AUPREC для угловых значений. Для и функционирует, DIMZIN dimensioning переменное средство управления, как продвижение и конечные нули написаны к строке результата. Дополнительные функции acdbDisToF () и acdbAngToF () преобразовывают строки назад в реальные значения (расстояния) или углы. Если пропускается строка, сгенерированная acdbRToS () или acdbAngToS (), acdbDisToF () и acdbAngToF () (соответственно), как гарантируют,  возвратят имеющее силу значение.
    Например, следующие показы фрагмента вызывают к acdbRToS () (. Проверка Ошибки не показывается, но должна быть включена в приложения.)
    Ads_real x = 17.5;
    char fmtval [12];
    // Точность - 3-ий параметр: 4 места в первом
    // Вызвать, 2 места в другие.
    AcdbRToS
    (x, 1, 4, fmtval); // Режим 1 = научный
    AcutPrintf
    (" Значение, отформатированное как %s\n ", fmtval);
    AcdbRToS
    (x, 2, 2, fmtval); // Режим 2 = десятичное число
    AcutPrintf
    (" Значение, отформатированное как %s\n ", fmtval);
    AcdbRToS
    (x, 3, 2, fmtval); // Режим 3 = разработка
    AcutPrintf
    (" Значение, отформатированное как %s\n ", fmtval);
    AcdbRToS
    (x, 4, 2, fmtval); // Режим 4 = архитектурный
    AcutPrintf
    (" Значение, отформатированное как %s\n ", fmtval);
    AcdbRToS
    (x, 5, 2, fmtval); // Режим 5 = дробный
    AcutPrintf
    (" Значение, отформатированное как %s\n ", fmtval);
    Они вызывают (принятие, что DIMZIN переменная равняется 0) отображают следующий
    Значения на экране текста AutoCAD.
    Значение, отформатированное как 1.7500E+01
    Значение, отформатированное как 17.50
    Значение, отформатированное как 1‘ -5.50 І

    Значение, отформатированное как 1’ -5 1/2 І

    Значение, отформатированное как 17 1/2

    Когда UNITMODE переменная системы установлена в 1, который определяет, что модули отображены как введено, строка, возвращенная acdbRToS () отличается для разработки (режим равняется 3), архитектурный (режим равняется 4), и дробный (режим равняется 5) модулям. Например, первые две линии предшествующего типового вывода были бы, тот же самый, но последние строки будет появляться следующим образом:

    Значение, отформатированное как 1 ‘ 5.50 І

    Значение, отформатированное как 1 ‘ 5-1/2 І

    Значение, отформатированное как 17-1/2

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

    acdbDisToF("1.7500E+01", 1, &result); // 1 = scientific

    acdbDisToF("17.50", 2, &result); // 2 = decimal

    // Note the backslashes. Needed for inches.

    acdbDisToF("1’-5.50\"", 3, &result); // 3 = engineering

    acdbDisToF("1’-5 1/2\"", 4, &result); // 4 = architectural

    acdbDisToF("17 1/2", 5, &result); // 5 = fractional

    Следующие показы фрагмента вызывают к acdbAngToS () которые являются подобными предыдущему acdbRToS () примеры.

    ads_real ang = 3.14159;

    char fmtval[12];

    // Precision is the 3rd argument: 0 places in the first

    // call, 4 places in the next 3, 2 in the last.

    acdbAngToS(ang, 0, 0, fmtval); // Mode 0 = degrees

    acutPrintf("Angle formatted as %s\n", fmtval);

    acdbAngToS(ang, 1, 4, fmtval); // Mode 1 = deg/min/sec

    acutPrintf("Angle formatted as %s\n", fmtval);

    acdbAngToS(ang, 2, 4, fmtval); // Mode 2 = grads

    acutPrintf("Angle formatted as %s\n", fmtval);

    acdbAngToS(ang, 3, 4, fmtval); // Mode 3 = radians

    acutPrintf("Angle formatted as %s\n", fmtval);

    acdbAngToS(ang, 4, 2, fmtval); // Mode 4 = surveyor’s


    acutPrintf("Angle formatted as %s\n", fmtval);

    Они вызывают ( все еще принятие что DIMZIN равняется 0) отображают следующие значения на экране текста AutoCAD.

    Angle formatted as 180

    Angle formatted as 180d0¢0²

    Angle formatted as 200.0000g

    Angle formatted as 3.1416r

    Angle formatted as W

    ОБРАТИТЕ ВНИМАНИЕ, что  UNITMODE переменная системы также воздействует на строки, возвращенные acdbAngToS () когда это возвращает строку в модулях инспектора (режим равняется 4). Если UNITMODE равняется 0, возвращенная строка может включать пробелы (например, “ N 45d E ”); если UNITMODE равняется 1, строка не содержит никакие пробелы (например, “N45dE”).

    AcdbAngToF() функциональные дополнения acdbAngToS (), так следующее вызывает весь набор параметр результата к тому же самому значению, 3.14159. (Это округлено до 3.1416 в примере, который использует радианы.)

    AcdbAngToF ("180", 0, *result); // 0 = градусы

    AcdbAngToF ("180d0" 0 \ "", 1, *result); // 1 = deg/min/sec

    AcdbAngToF ("200.0000g", 2, *result); // 2 = grads

    AcdbAngToF ("3.1416r", 3, *result); // 3 = радианы

    AcdbAngToF ("W", 4, *result); // 4 = инспектор

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

    Struct resbuf

    Следующая структура буфера результата, resbuf, определена в конъюнкции с объединением, ads_u_val, который размещает различный AutoCAD и ObjectARX типы данных, следующим образом:
    union ads_u_val {
    ads_real rreal;
    ads_real rpoint[3];
    short rint; // Must be declared short, not int.
    char *rstring;
    long rlname[2];
    long rlong;
    struct ads_binary rbinary;
    };
    struct resbuf {
    struct resbuf *rbnext; // Linked list pointer
    short restype;
    union ads_u_val resval;
    };
    ОБРАТИТЕ ВНИМАНИЕ, что  поле long integer - resval.rlong - подобно двоичному полю данных resval.rbinary; оба держат расширенные данные примитива.
    Следующий рисунок показывает схематическую форму списка буфера результата:
    Struct resbuf

    SubErase, subOpen, subClose, and subCancel

    Ф-ции erase(), open(), close(), и cancel() все имеют соответствующие виртуальные функции, начинающиеся с префиксной замены. Вы можете отменять эти вспомогательные функции, чтобы обеспечить дополнительные функциональные возможности для полученных классов. Вспомогательная функция вызвана невиртуальной “главной” функцией. Например, erase() - subErase(). Сигнатура для subErase() следующие:
    virtual Acad::ErrorStatus
    subErase(Adesk::Boolean pErasing);
     Перегрузите вспомогательную функцию
    1 Проверяют правильность вашей окрестности. Например, если ваш объект имеет жесткую ссылку указателя к другому объекту, и ваш объект не стирается, Вы можете проверять, чтобы объект, к которому Вы относите все еще, существовал. Если имеются проблемы, немедленно возвращают соответствующее состояние ошибки и не упускают сообщение, потому что ваше плохое состояние ошибки эффективно уничтожит операцию.
    2, если все - OK, затем вызывает Ваше Родительское подстирание:: () функция. Исследуйте его результат. Если это не возвращает eOK, то возвращается.
    3, если все - OK, затем исполняет ваши действия.
    Лучше не изменить{*заменить*} любое государство{*состояние*} во вспомогательной функции. Если Вы изменили{*заменили*} государство{*состояние*}, затем пробовать изменить{*заменить*} это после вызова родительского выполнения класса той же самой функции (в случае, если код ошибки возвращен). Если Вы изменили{*заменить*} государство{*состояние*} перед вызовом родительской функции класса, то подготовлены, чтобы полностью изменить это, если родительский класс возвращает плохое состояние.
    Следующий пример показывает выполнению subErase() функция, которая называется, когда объект стерт. subErase() проверяет жесткие ссылки указателя к другим объектам и стирает их также.
    class AsdkEllipse : public AcDbEllipse
    // Этот класс расширяет AcDbEllipse,  добавляясь в функциональных возможностях
    // Сохранять динамический массив жесткого объекта IDs указателя.
    //
    // subErase () функция элемента отменяет и

    // Осуществленный, так, когда объект этого класса

    // Стертый, объекты, указанные жестким указателем IDs

    // Сохраненный в пределах объекта будет также стерт.

    //

    {

    public:

    ACRX_DECLARE_MEMBERS(AsdkEllipse);

    AsdkEllipse() {};

    AsdkEllipse(const AsdkEllipse&);

    AsdkEllipse(const AcDbObjectIdArray& ellipses)

    : mEllipseIds(ellipses) {};

    AsdkEllipse(const AcGePoint3d& center,

    const AcGeVector3d& unitNormal,

    const AcGeVector3d& majorAxis,

    double radiusRatio,

    double startAngle = 0.0,

    double endAngle = 6.28318530717958647692);

    AsdkEllipse(const AcDbObjectIdArray& ellipses,

    const AcGePoint3d& center,

    const AcGeVector3d& unitNormal,

    const AcGeVector3d& majorAxis,

    double radiusRatio,

    double startAngle = 0.0,

    double endAngle = 6.28318530717958647692);

    AcDbObjectId ellipseId(unsigned short which);

    Acad::ErrorStatus setEllipseId(

    const AcDbObjectId& objId, unsigned short which);

    Acad::ErrorStatus setEllipseIds(

    const AcDbObjectIdArray& Ids);

    Acad::ErrorStatus appendId(const AcDbObjectId& objId);

    Acad::ErrorStatus appendIds(

    const AcDbObjectIdArray& objIds);

    inline Adesk::Boolean removeId(

    const AcDbObjectId& objId);

    // AcDbObject overrides.

    //

    virtual Acad::ErrorStatus subErase(

    Adesk::Boolean pErasing);

    virtual Acad::ErrorStatus dwgInFields(

    AcDbDwgFiler* filer);

    virtual Acad::ErrorStatus dwgOutFields(

    AcDbDwgFiler* filer) const;

    virtual Acad::ErrorStatus dxfInFields(

    AcDbDxfFiler* filer);

    virtual Acad::ErrorStatus dxfOutFields(

    AcDbDxfFiler* filer) const;

    virtual Acad::ErrorStatus wblockClone(

    AcRxObject* pOwnerObject,

    AcDbObject*& pClonedObject,

    AcDbIdMapping& idMap,

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

    // AcDbEntity overrides.

    //

    virtual void list() const;

    // AcRxObject overrides.

    //

    virtual AcRxObject* clone() const;

    private:

    AcDbObjectIdArray mEllipseIds;

    static int mInFlux; // == 1 when first object’s

    // subErase is active.

    };

    ACRX_DXF_DEFINE_MEMBERS(AsdkEllipse, AcDbEllipse,


    AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent, 0, ASDKELLIPSE,

    REFERENC);

    // Static class data member definition.

    //

    int AsdkEllipse::mInFlux = Adesk::kFalse;

    AsdkEllipse::AsdkEllipse(const AsdkEllipse& master)

    {

    set(master.center(), master.normal(),

    master.majorAxis(), master.radiusRatio(),

    master.startAngle(), master.endAngle());

    mEllipseIds = master.mEllipseIds;

    }

    AsdkEllipse::AsdkEllipse(const AcGePoint3d& center,

    const AcGeVector3d& unitNormal,

    const AcGeVector3d& majorAxis,

    double radiusRatio,

    double startAngle,

    double endAngle) :

    AcDbEllipse(center, unitNormal, majorAxis, radiusRatio,

    startAngle, endAngle)

    { }

    AsdkEllipse::AsdkEllipse(const AcDbObjectIdArray& ellipses,

    const AcGePoint3d& center,

    const AcGeVector3d& unitNormal,

    const AcGeVector3d& majorAxis,

    double radiusRatio,

    double startAngle,

    double endAngle) :

    AcDbEllipse(center, unitNormal, majorAxis, radiusRatio,

    startAngle, endAngle), mEllipseIds(ellipses)

    { }

    AcDbObjectId

    AsdkEllipse::ellipseId(unsigned short which)

    {

    assertReadEnabled();

    if (which > mEllipseIds.length())

    return AcDbObjectId::kNull;

    return mEllipseIds[which];

    }

    Acad::ErrorStatus

    AsdkEllipse::setEllipseId(const AcDbObjectId& objId,

    unsigned short which)

    {

    assertWriteEnabled();

    if (which > mEllipseIds.length())

    return Acad::eInvalidIndex;

    mEllipseIds[which] = objId;

    return Acad::eOk;

    }

    Acad::ErrorStatus

    AsdkEllipse::setEllipseIds(const AcDbObjectIdArray& objIds)

    {

    assertWriteEnabled();

    if (objIds.length() == 0)

    return Acad::eNullObjectId;

    mEllipseIds = objIds;

    return Acad::eOk;

    }

    Acad::ErrorStatus

    AsdkEllipse::appendId(const AcDbObjectId& objId)

    {

    assertWriteEnabled();

    if (objId == AcDbObjectId::kNull)

    return Acad::eNullObjectId;

    mEllipseIds.append(objId);

    return Acad::eOk;

    }

    Acad::ErrorStatus

    AsdkEllipse::appendIds(const AcDbObjectIdArray& objIds)

    {

    assertWriteEnabled();

    if (objIds.length() == 0)

    return Acad::eNullObjectId;


    mEllipseIds.append(objIds);

    return Acad::eOk;

    }

    inline Adesk::Boolean

    AsdkEllipse::removeId(const AcDbObjectId& objId)

    {

    assertWriteEnabled();

    return mEllipseIds.remove(objId);

    }

    // This implementation of subErase opens and erases all

    // objects that this entity has hard pointer references

    // to. The effect is that when one AsdkEllipse is erased,

    // all the others it has hard pointers to also erase as

    // a "group".

    //

    Acad::ErrorStatus

    AsdkEllipse::subErase(Adesk::Boolean pErasing)

    {

    Acad::ErrorStatus es = AcDbEllipse::subErase(pErasing);

    if (es != Acad::eOk)

    return es;

    if (mInFlux == Adesk::kFalse) {

    mInFlux = Adesk::kTrue;

    AsdkEllipse *pEllipse;

    int es;

    for (int i = 0; i < mEllipseIds.length(); i++) {

    es = acdbOpenObject(pEllipse, mEllipseIds[i],

    AcDb::kForWrite, Adesk::kTrue);

    if (es != Acad::eOk)

    continue;

    pEllipse->erase(pErasing);

    pEllipse->close();

    }

    mInFlux = Adesk::kFalse;

    }

    return Acad::eOk;

    }

    Acad::ErrorStatus

    AsdkEllipse::dwgInFields(AcDbDwgFiler* filer)

    {

    assertWriteEnabled();

    AcDbEllipse::dwgInFields(filer);

    mEllipseIds.setLogicalLength(0);

    int idCount;

    filer->readInt32((long*)&idCount);

    AcDbHardPointerId objId;

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

    filer->readItem(&objId);

    mEllipseIds.append(objId);

    }

    return filer->filerStatus();

    }

    Acad::ErrorStatus

    AsdkEllipse::dwgOutFields(AcDbDwgFiler* filer) const

    {

    assertReadEnabled();

    AcDbEllipse::dwgOutFields(filer);

    filer->writeInt32(mEllipseIds.length());

    for (int i = 0; i < mEllipseIds.length(); i++) {

    filer->writeHardPointerId(mEllipseIds[i]);

    }

    return filer->filerStatus();

    }

    Acad::ErrorStatus

    AsdkEllipse::dxfInFields(AcDbDxfFiler* filer)

    {

    assertWriteEnabled();

    Acad::ErrorStatus es = AcDbEllipse::dxfInFields(filer);

    if (es != Acad::eOk) {

    return es;

    }

    // Check to see if we’re at the right subclass data

    // marker.

    //

    if (!filer->atSubclassData("AsdkEllipse")) {

    return Acad::eBadDxfSequence;


    }

    struct resbuf inbuf;

    AcDbObjectId objId;

    int idCount;

    filer->readItem(&inbuf);

    if (inbuf.restype == AcDb::kDxfInt32) {

    idCount = inbuf.resval.rint;

    } else {

    filer->pushBackItem();

    filer->setError(Acad::eInvalidDxfCode,

    "\nError: expected group code %d",

    AcDb::kDxfInt32);

    return filer->filerStatus();

    }

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

    es = filer->readItem(&inbuf);

    if (es != Acad::eOk) {

    filer->setError(Acad::eMissingDxfField,

    "\nError: expected more group code %d’s",

    AcDb::kDxfHardPointerId);

    return filer->filerStatus();

    }

    if (inbuf.restype == AcDb::kDxfHardPointerId) {

    acdbGetObjectId(objId, inbuf.resval.rlname);

    mEllipseIds.append(objId);

    } else {

    filer->pushBackItem();

    filer->setError(Acad::eInvalidDxfCode,

    "\nError: expected group code %d",

    AcDb::kDxfHardPointerId);

    return filer->filerStatus();

    }

    }

    return filer->filerStatus();

    }

    Acad::ErrorStatus

    AsdkEllipse::dxfOutFields(AcDbDxfFiler* filer) const

    {

    assertReadEnabled();

    AcDbEllipse::dxfOutFields(filer);

    filer->writeItem(AcDb::kDxfSubclass, "AsdkEllipse");

    filer->writeInt32(AcDb::kDxfInt32,

    mEllipseIds.length());

    for (int i = 0; i < mEllipseIds.length(); i++) {

    filer->writeObjectId(AcDb::kDxfHardPointerId,

    mEllipseIds[i]);

    }

    return filer->filerStatus();

    }

    void

    AsdkEllipse::list() const

    {

    assertReadEnabled();

    AcDbEllipse::list();

    acutPrintf("\nClass:\t%s", isA()->name());

    for (int i = 0; i < mEllipseIds.length(); i++) {

    acutPrintf("\nReferenceId[%d]:\t%ld", i,

    (mEllipseIds[i]).asOldId());

    }

    }

    // Called whenever an object of this class is dragged,

    // moved, stretched, rotated, etc. so be careful what

    // this function is made to do.

    //

    AcRxObject*

    AsdkEllipse::clone() const

    {

    assertReadEnabled();

    return new AsdkEllipse(*this);

    }

    Acad::ErrorStatus

    AsdkEllipse::wblockClone(

    AcRxObject* pOwnerObject,

    AcDbObject*& pClonedObject,


    AcDbIdMapping& idMap,

    Adesk::Boolean isPrimary) const

    {

    assertReadEnabled();

    static AcDbObjectId btr, pspace = AcDbObjectId::kNull;

    AcTransaction *pTrans = NULL;

    pClonedObject = NULL;

    if (pspace == AcDbObjectId::kNull) {

    AcDbBlockTable *pTable;

    database()->getSymbolTable(pTable, AcDb::kForRead);

    pTable->getAt(ACDB_PAPER_SPACE, pspace);

    pTable->close();

    }

    if ( idMap.deepCloneContext() == AcDb::kDcXrefBind && ownerId() == pspace)

    return Acad::eOk;

    // Have we already done this entity ?

    //

    AcDbIdPair idPair(objectId(), (AcDbObjectId)NULL, Adesk::kTrue);

    if (idMap.compute(idPair) == TRUE && idPair.value()  != NULL)

    {

    pClonedObject = NULL;

    return Acad::eOk;

    }

    AcDbBlockTableRecord *pBTR = AcDbBlockTableRecord::cast(pOwnerObject);

    if (pBTR != NULL) {

    if (isPrimary == Adesk::kTrue)

    btr = pBTR->objectId();

    else

    btr = AcDbObjectId::kNull;

    } else if (btr != AcDbObjectId::kNull) {

    pTrans = actrTransactionManager->startTransaction();

    pTrans->getObject((AcDbObject*&)pBTR, btr,

    AcDb::kForWrite);

    pOwnerObject = pBTR;

    }

    Acad::ErrorStatus es = AcDbEllipse::wblockClone(pOwnerObject,

    pClonedObject, idMap, btr != AcDbObjectId::kNull);

    if (pTrans)

    actrTransactionManager->endTransaction();

    acutPrintf("\nWblockClone error status: %s",

    acadErrorStatusText(es));

    return Acad::eOk;

    }

    void

    createEllipses()

    {

    const ellipseCount = 10;

    AsdkEllipse *pEllipse;

    pEllipse = new AsdkEllipse(AcGePoint3d(4.0, 4.0, 0.0),

    AcGeVector3d(0.0, 0.0, 1.0),

    AcGeVector3d(2.0, 0.0, 0.0),

    0.5);

    AcDbVoidPtrArray ellipses;

    ellipses.append(pEllipse);

    // Now use the getTransformedCopy() function with a

    // scaling matrix (in X & Y only) to create new

    // AsdkEllipses, each 0.5 units larger than the last in

    // the X & Y direction, but identical in the Z

    // direction. This would be similar to the

    // getOffsetCurves() function, but that function

    // returns AcDbSpline entities instead of AcDbEllipses.

    //


    double j = 1.1;

    AcGeMatrix3d scale;

    for (int i = 0; i < ellipseCount; i++, j += 0.1) {

    scale.setToScaling(j, pEllipse->center());

    scale.entry[2][2] = 1.0; // Z scaling == 1

    // getTransformed copy uses this->clone() to create

    // a new object, which the ent pointer is assigned

    // to point to. Therefore, ent should NOT point to an

    // existing entity or there will be a memory leak!

    //

    // Since this->clone() is used, the AsdkEllipse class

    // must override this member function to

    // be sure that an AsdkEllipse is created instead

    // of just an AcDbEllipse.

    //

    AsdkEllipse *pNextEllipse;

    ((AsdkEllipse*)ellipses[0])->getTransformedCopy(

    scale, (AcDbEntity*&)pNextEllipse);

    ellipses.append(pNextEllipse);

    }

    AcDbBlockTable *pBlockTable;

    acdbHostApplicationServices()->workingDatabase()

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

    AcDbBlockTableRecord *pBlockTableRecord;

    pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord,

    AcDb::kForWrite);

    pBlockTable->close();

    AcDbObjectIdArray ellipseIds;

    AcDbObjectId tempId;

    for (i = 0; i < ellipses.length(); i++) {

    pBlockTableRecord->appendAcDbEntity(tempId,

    (AsdkEllipse*)ellipses[i]);

    ellipseIds.append(tempId);

    }

    pBlockTableRecord->close();

    // Set up the hard pointers and close the ellipses.

    //

    for (i = 0; i < ellipses.length(); i++) {

    // Add in all the IDs.

    //

    ((AsdkEllipse*)ellipses[i])

    ->setEllipseIds(ellipseIds);

    // Now remove the object ID of the "*this" ellipse

    // so it doesn’t reference itself.

    //

    ((AsdkEllipse*)ellipses[i])->removeId(

    ((AsdkEllipse*)ellipses[i])->objectId());

    ((AsdkEllipse*)ellipses[i])->close();

    }

    }

    void

    initApp()

    {

    acedRegCmds->addCommand("ASDK_ELLIPSES",

    "ASDK_ELLIPSES", "ELLIPSES",

    ACRX_CMD_MODAL, createEllipses);

    AsdkEllipse::rxInit();

    acrxBuildClassHierarchy();

    }

    void

    unloadApp()

    {

    acedRegCmds->removeGroup("ASDK_ELLIPSES");

    // Remove the AsdkEllipse class from the ACRX runtime

    // class hierarchy. If this is done while the database is

    // still active, it should cause all objects of class

    // AsdkEllipse to be turned into proxies.

    //

    deleteAcRxClass(AsdkEllipse::desc());

    }

    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();

    }

    return AcRx::kRetOK;

    }

    Связь между Приложениями

    Функция ObjectARX acedInvoke () в одном приложении используется, чтобы вызвать внешние функции, определенные и осуществленные другими приложениями ObjectARX.
    Внешняя функция, вызванная acedInvoke() должна быть определена в настоящее время загруженным ObjectARX-приложением.
    AcedInvoke() функция вызывает внешнюю функцию именем, что его приложение определило в acedDefun() запрос, который является именем функции, что AutoLISP вызывает, чтобы вызвать функцию. Если внешняя функция была определена как команда AutoLISP, с “ C: ” как префикс к его имени, эти символы должны быть включены в строку, как которая acedInvoke () определяет (когда команда вызвана с выражением AutoLISP).
    ПРЕДУПРЕЖДЕНИЕ! Поскольку приложения, загруженные в то же самое время не могут иметь двойные имена функции, Вы должны брать это во внимание при проектировании приложения, которое использует больше чем единственный программный файл; избегите проблемы со схемой обозначения или соглашением, которое гарантирует, что имя каждой внешней функции будет уникально. Лучшее решение состоит в том, чтобы использовать ваш Зарегистрированный Символ Разработчика (RDS) как префикс.
    Имя внешней функции, и любых значений параметра, которых это требует, пропускают к acedInvoke() в форме списка связей буферов результатов. Это также возвращает его результат в списке буфера результата; второй параметр к acedInvoke () - адрес указателя буфера результата.
    Следующая типовая функция вызывает acedInvoke () чтобы вызвать факт функции факториала () в типовой программе fact.cpp:
    static void test()
    {
    int stat, x = 10;
    struct resbuf *result = NULL, *list;
    // Get the factorial of x from file fact.cpp.
    list = acutBuildList(RTSTR, "fact", RTSHORT, x, RTNONE);
    if (list != NULL) {
    stat = acedInvoke(list, &result);
    acutRelRb(list);
    }
    if (result != NULL) {
    acutPrintf("\nSuccess: factorial of %d is %d\n", x, result->resval.rint);
    acutRelRb(result);
    }
    else
    acutPrintf("Test failed\n");

    }

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

    Когда acedRegFunc() вызван, чтобы регистрировать функцию, ObjectARX вызывает функцию непосредственно, без того, чтобы пройти цикл отправки приложения. Чтобы определять функцию, вызовите acedRegFunc ().

    Внешний функциональный обработчик, зарегистрированный acedRegFunc() не должен иметь никакие параметры и должен возвратить целое число (который является одним из прикладного результата, закодирует — или RSRSLT или RSERR).

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

    typedef int (*ADSFUNC) (void);

    // Сначала, определите структуру таблицы: строка, дающая имя AutoCAD функции,

    //  и указателя на функцию, возвращающую тип int.

    struct func_entry {char *func_name; ADSFUNC func;};

    // Объявить функции, которые обрабатывают, вызывает.

    int fact (void); // Remove the arguments

    int squareroot (void);

    // Здесь мы определяем массив имен функции и обработчиков.

    //

    static struct func_entry func_table[] =

    {              {"fact", fact},

    {"sqr", squareroot},

    };

    ...

    static int funcload()

    {

    int i;

    for (i = 0; i < ELEMENTS(func_table); i++) {

    if (!acedDefun(func_table[i].func_name, i))

    return RTERROR;

    if (!acedRegFunc(func_table[i].func, i))

    return RTERROR;

    }

    return RTNORM;

    }

    Как показывают выборки кода, первый параметр к acedRegFunc () - указатель функции (названный по имени функциональный обработчик, определенный в исходном тексте), а не внешнее имя функции, определенное acedDefun () и вызванный AutoLISP или acedInvoke (). И acedDefun () и acedRegFunc () передают тот же самый целочисленный функциональный код .

    Если зарегистрированная функция должна отыскать параметры, это должно делать так,  делая ее собственный запрос к acedGetArgs ().


    AcedGetArgs () запрос перемещен, чтобы быть в пределах функционального fact(). Указатель буфера результата rb сделан переменной скорее чем параметр. (Это не соответствует запросу к fact () в dofun () функция. Если все внешние функции зарегистрированы, поскольку этот пример принимает, dofun () функция может быть удалена полностью; см. примечание, которое следует за этим примером.) новый код показывается в типе жирного начертания:

    static int fact()

    {

    int x;

    struct resbuf *rb;

    rb = acedGetArgs();

    if (rb == NULL)

    return RTERROR;

    if (rb->restype == RTSHORT) {

    x = rb->resval.rint; // Save in local variable.

    } else {

    acdbFail("Argument should be an integer.");

    return RTERROR;

    }

    if (x < 0) { // Check the argument range.

    acdbFail("Argument should be positive.");

    return RTERROR;

    } else if (x > 170) { // Avoid floating-point overflow.

    acdbFail("Argument should be 170 or less.");

    return RTERROR;

    }

    acedRetReal(rfact(x)); // Call the function itself, and

    // return the value to AutoLISP.

    return RTNORM;

    }

    Сопоставимое изменение было бы должно быть сделано к squareroot().

    ОБРАТИТЕ ВНИМАНИЕ, вызывает ли приложение acedRegFunc() чтобы регистрировать обработчик для каждой внешней функции, это определяет, это может предполагать, что эти функции будут вызваны acedInvoke(), и это может опустить kInvkSubrMsg случай acrxEntryPoint () функция. Если Вы проектируете приложение, которое требует больше чем единственный файл кода ObjectARX, эта методика предпочтительна, потому что это размещает бремя обработки функции, вызывает ObjectARX библиотеку скорее чем на acrxEntryPoint() функцию.

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


    Связь между Приложениями

    В иллюстрации выше,

    § A_tan () вызывает B_sin ()

    § A_tan () вызывает C_cos ()

    § B_sin () вызывает A_pi ()

    § C_cos () вызывает A_pi ()

    Где приложение A определяет A_tan () и A_pi (), приложение B определяет B_sin (), и приложение C определяет C_cos (). A_pi () функция должен быть зарегистрирован acedRegFunc().

    Чтобы предотвращать acedInvoke() от сообщающих ошибок регистрации, регистрируйте любую внешнюю функцию, которая, как предполагается,  будет вызвана с acedInvoke().

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

    Свойства Уровня

    AcDbLayerTableRecord класс содержит функции члена для определения множества свойств уровня, которые затрагивают дисплей их связанных примитивов.
    Все примитивы должны обратиться{*отнестись*} к правильной{*допустимой*} записи таблицы уровня. Руководство программиста AutoCAD обеспечивает детальное описание свойств уровня.
    Следующие разделы перечисляют функции члена для установки и запроса свойств уровня.
    Frozen/Thawed  (Заморозить / таять)
    Когда уровень закрепляется, графика не восстановлена.
    void AcDbLayerTableRecord::setIsFrozen(Adesk::Boolean);
    Adesk::Boolean
    AcDbLayerTableRecord::isFrozen() const;
    On/Off  (Вкл\выкл)
    Когда уровень ВЫКЛЮЧЕН, графический не отображены.
    void AcDbLayerTableRecord::setIsOff(Adesk::Boolean);
    Adesk::Boolean
    AcDbLayerTableRecord::isOff() const;
    Viewport
    (Область просмотра)

    Этот setVPDFLT () функция определяет,является ли уровень по умолчанию видимым или невидимым в новых областях просмотра.
    void AcDbLayerTableRecord::setVPDFLT(Adesk::Boolean);
    Adesk::Boolean
    AcDbLayerTableRecord::VPDFLT() const;
    Locked/Unlocked
    (Блокировал / разблокировал)

    Примитивы на блокированном уровне не могут изменяться пользователем AutoCAD или открыт для записи () функция в пределах программы.
    void AcDbLayerTableRecord::setIsLocked(Adesk::Boolean);
    Adesk::Boolean
    AcDbLayerTableRecord::isLocked() const;
    Color (Цвет)
    Цвет, установленный setColor () функция используется, когда цвет примитива - BYLAYER.
    void AcDbLayerTableRecord::setColor(const AcCmColor &color);
    AcCmColor
    AcDbLayerTableRecord::color() const;
    Linetype
    Linetype, установленный setLinetypeObjectId () функция используется, когда linetype примитива - BYLAYER.
    void AcDbLayerTableRecord::setLinetypeObjectId(AcDbObjectId);
    AcDbObjectId
    AcDbLayerTableRecord::linetypeObjectId() const;

    Таблицы идентификаторов

    Имена, используемые в записях таблицы идентификаторов и в словарях должны следовать за этими правилами:
    § Имена может быть любая длина в ObjectARX, но имена символа, введенные пользователями в AutoCAD ограничены 255 символами.
    § AutoCAD сохраняет регистр имен, но не использует регистр на сравнениях. Например, AutoCAD полагает ", что “этаж" будет тем же самым символом как “ЭТАЖ”.
    § Имена может быть составлен из всех символов, позволенных в именах файла Windows NT, кроме запятой (,), backquote (‘), точка с запятой (;), и знак "=" (=).
    База данных AutoCAD содержит следующие таблицы идентификаторов (в круглых скобках -  имя класса и команда AutoCAD, используемая для добавления входов):
    § N Таблица блоков (AcDbBlockTable; BLOCK)
    § N таблица Уровня (AcDbLayerTable; LAYER)
    § N Текстовая таблица стиля (AcDbTextStyleTable; STYLE)
    § N Linetype таблица (AcDbLinetypeTable; LTYPE)
    § N таблица Представления{*вида*} (AcDbViewTable; VIEW)
    § N
    таблица ВЕРХНИХ РЕГИСТРОВ (AcDbUCSTable; UCS)
    § N
    таблица Области просмотра (AcDbViewportTable; VPORT)
    § N таблица приложений Registered (AcDbRegAppTable)
    § N
    таблица стилей Измерения (AcDbDimStyleTable; DIMSTYLE)
    Каждая таблица содержит объекты соответствующего подкласса AcDbSymbolTableRecord.
    Каждый класс таблицы идентификаторов обеспечивает getAt () функцией для поиска записи, указанной по имени. Сигнатуры для перезагруженных форм getAt () функция следующие. (##BASE_NAME## Замещает любой из девяти типов класса таблицы идентификаторов.)

    Acad::ErrorStatus
    AcDb##BASE_NAME##Table::getAt(const char* pEntryName,
    AcDb::OpenMode mode,
    AcDb##BASE_NAME##TableRecord*&
    pRecord,
    Adesk::Boolean openErasedRecord =
    Adesk::kFalse) const;
    или
    Acad::ErrorStatus
    AcDb##BASE_NAME##Table::getAt(const char* pEntryName,
    AcDbObjectId& recordId,
    Adesk::Boolean getErasedRecord =
    Adesk::kFalse) const;
    Эта первая версия этой функции возвращает указатель на открытую запись в pRecord, если запись соответствия найдена, и операция открытия (с указанным режимом) преуспевает. Если openErasedRecord - kTrue, функция возвращает объект, даже если это было стерто. Если openErasedRecord - kFalse, функция возвращает указатель NULL и состояние ошибки eWasErased для стертых объектов.
    Вторая версия getAt () функция возвращает AcDbObjectId записи, указанной по имени в значении recordId, если запись соответствия найдена.
    Если getErasedRecord - kTrue, функция возвращает объект соответствия, даже если это было стерто. Объект не открыт.
    Как только Вы получили запись и открыли это, Вы можете получить и устанавливать различные значения члена. Для определенного класса записи таблицы идентификаторов для законченного списка компонентных функций класса, см. ObjectARX Ссылку.
    Другие важные функции, обеспеченные всеми классами таблицы идентификаторов -, has() и add() функции. См. пример в “ Создание и Изменение Записи Таблицы Уровня ” на странице 150.
    Сигнатура для has()
    Adesk::Boolean
    AcDb##BASE_NAME##Table::has(const char* pName) const;
    has() возвращает kTrue, если таблица содержит запись с именем, которое соответствует pName.
    add() имеет следующие сигнатуры:
    Acad::ErrorStatus
    AcDb##BASE_NAME##Table::add(AcDb##BASE_NAME##TableRecord*
    pRecord);
    Acad::ErrorStatus
    AcDb##BASE_NAME##Table::add(AcDbObjectId& recordId,
    AcDb##BASE_NAME##TableRecord*
    pRecord);
    Эта функция добавляет запись, указанную pRecord, и к базе данных, содержащей таблицу и таблицу непосредственно. Если добавления преуспевают, и параметр pId - не-NULL, это установлено в AcDbObjectId записи в базе данных.

    Текст

    Пример в этом разделе показывает использование AcGiTextStyle класса. Это рисует прямоугольник вокруг части текста AcGi, который может ориентироваться и расположен где-нибудь в пространстве.
    Нормаль и векторы направления текста должны быть перпендикулярны к друг другу. Если вы неуверены из направлений, полагаете, что  направление будет по X оси и нормали по Z оси в правосторонней координатной системе.
    Вычислите Y ось от них. Тогда векторное произведение Y оси к Z оси даст Вам интерпретацию нормального плана направления. Убедитесь, что направление не выровнено с нормалью, или Вы не будете иметь направления относительно нормали.
    AcGiTextStyle:: loadStyleRec () функция загружает шрифт, если это уже не загружено. (Функция This не загружает ACAD
    СТИЛЬ.) Его возвращаемые значения следующие:
    0x10       Другой файл (не FONTALT) открытый на месте имени файла BigFont
    0x08       Другой файл (не FONTALT) открытый на месте имени файла
    0x04       имя файла BigFont не сумел быть загруженным
    0x02       Имя файла не сумел быть загруженным
    0x01       Файлы открылся как запрашивается
    Текст может масштабироваться способом путей. Используйте AcGiTextStyle:: setTextSize () чтобы масштабировать ширину и высоту текста в то же самое время. Используйте setXScale () чтобы масштабировать ширину текста. Используйте setTrackingPercent () чтобы определить, как символы специфического шрифта помещены рядом с друг другом. Если Вы определяете значение 1.0, интервал не изменяется; если Вы определяете меньше чем 1.0, символы сожмут вместе; и если это - больше чем 1.0, символы, будут дальше обособленно. Этот пример устанавливает трэкинг процент к значению .80.
    AcGiTextStyle::extents
    () функция возвращает размер мировой координаты поля ограничения текста. Если penups параметр - kTrue, то любые нерисовавшие перьевые шаги, сделанные, в то время как пользователь рисовал текст, будут включены в поле ограничения. Необработанная опция сообщает вычислению игнорировать обработку управляющего кода (так, чтобы “%%%” не интерпретировался бы как единственный знак процента, но как три знака процента).

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

    Adesk::Boolean

    AsdkTextStyleSamp::worldDraw(AcGiWorldDraw* pW)

    {

    AcGePoint3d pos(4.0, 4.0, 0.0);

    AcGeVector3d norm(0.0, 0.0, 1.0);

    AcGeVector3d dir(-1.0, -0.2, 0.0);

    char *pStr = "This is a percent, ’%%%’.";

    int len = strlen(pStr);

    AcGiTextStyle style;

    AcGeVector3d vec = norm;

    vec = vec.crossProduct(dir);

    dir = vec.crossProduct(norm);

    style.setFileName("txt.shx");

    style.setBigFontFileName("");

    int status;

    if (!((status = style.loadStyleRec()) & 1))

    pStr = "Font not found.";

    pW->geometry().text(pos, norm, dir, pStr, len,

    Adesk::kFalse, style);

    pos.y += 2.0;

    style.setTrackingPercent(80.0);

    style.setObliquingAngle(10.0);

    AcGePoint2d ext = style.extents(pStr, Adesk::kFalse,

    strlen(pStr), Adesk::kFalse);

    pW->geometry().text(pos, norm, dir, pStr, len,

    Adesk::kFalse, style);

    // Draw a rectangle around the last text drawn.

    // First, create a polyline the size of the

    // bounding box. Then, transform it to the

    // correct orientation, and then to the location of the

    // text.

    // Compute the matrix that orients the box.

    //

    AcGeMatrix3d textMat;

    norm.normalize();

    dir.normalize();

    AcGeVector3d yAxis = norm;

    yAxis = yAxis.crossProduct(dir);

    yAxis.normalize();

    textMat.setCoordSystem(AcGePoint3d(0.0, 0.0, 0.0), dir, yAxis, norm);

    // Create the bounding box and enlarge it a little.

    //

    double offset = ext.y / 2.0;

    AcGePoint3d verts[5];

    verts[0] = verts[4] = AcGePoint3d(-offset, -offset, 0.0);

    verts[1] = AcGePoint3d(ext.x + offset, -offset, 0.0);

    verts[2] = AcGePoint3d(ext.x + offset, ext.y + offset, 0.0);

    verts[3] = AcGePoint3d(-offset, ext.y + offset, 0.0);

    // Orient and then translate each point in the

    // bounding box.

    //

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

    verts[i].transformBy(textMat);

    verts[i].x += pos.x;

    verts[i].y += pos.y;

    verts[i].z += pos.z;

    }

    pW->geometry().polyline(5, verts);

    return Adesk::kTrue;

    }

    Тип Регенерации Области просмотра

    С тех пор AcGi - только спецификация интерфейса, это может использоваться для многих различных целей. В AutoCAD AcGi спецификация имеет несколько различных выполнения, каждый с определенной целью. 2D-display канал используется, чтобы генерировать 2-ые изображения, отображенные на экране, и имеется различная трехмерная система для постоянно представляемых видов. В дополнение к этим связанным дисплеем выполнению, имеется несколько другие, включая любого, что Вы можете развиваться.
    Важно знать два других AcGi выполнения, используемые двигателем базы данных. Первый - для полномочного графического генерирования, и второй используется, чтобы взорвать объект в основные ObjectDBX примитивы. Полномочное графическое выполнение используется, когда заказной объект сохранен, сохранять графику в метафайле, который можно повторно запускать, когда рисунок загружен на системе, где заказное приложение не доступно. Взрывающееся выполнение используется взрывающимся механизмом и обнаружить границы в пределах сложного объекта.
    Это могло бы быть важно для Вас, чтобы различить между этими различными выполнением.
    Поэтому, AcGi выставляет тип регенерации области просмотра, котором можно делать запрос от вашего worldDraw () метод.
    Тип регенерации области просмотра установлен в соответствии с AutoCAD. Вы можете сделать запрос его значения, используя AcGiWorldDraw:: regenType () функция. Значения для AcGiRegenType
  • kAcGiStandardDisplay - типичный режим рисунка и используется, когда пользователь выпускает команду REGEN или редактирует вход. Примитивы должны быть представлены в каркасе в этом режиме.

  • kAcGiHideOrShadeCommand исполняет удаление невидимой линии и указывает, что команда HIDE ИЛИ SHADE - в действительности. Примитивы должны быть представлены, используя лица в этом режиме.

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

  • kAcGiSaveWorldDrawForR12 - тип, используемый для взрывающейся операции.

  • kAcGiSaveWorldDrawForProxy - тип, используемый для генерирования полномочной графики. В этом случае все ваше исполнение должно быть сделано в worldDraw () так как viewportDraw () не поддержан для полномочной графики.


  • Тип заполнения

    Заполняющийся тип перечисленное значение, AcGiFillType, может иметь одно из двух значений:
  • kAcGiFillAlways

  • kAcGiFillNever

  • Примитивы, которые могут быть заполнены - круги, многоугольники, оболочки, сети, текст, образовывают дугу сектора, и образовывают дугу аккорды. Ломаные линии и простые дуги не могут быть заполнены.
    Прежде, чем AutoCAD вызывает worldDraw (), это устанавливает заполняющийся тип в зависимости от перегенерального типа. Если перегенеральный тип - kAcGiStandardDisplay, AutoCAD устанавливает заполняющийся тип в kAcGiFillNever. Иначе, AutoCAD устанавливает заполняющийся тип в kAcGiFillAlways. Это значение повторно инициализировано согласно перегенеральному типу прежде, чем viewportDraw () вызван.
    Если пользователь выпускает определение команды FILL, чтобы выключить режим Fill, никакие объекты не заполнены независимо от перегенерального типа. Точно так же, если пользователь явно включает режим Fill, объекты будут заполнены. Если пользователь не выпускает команду FILL, и AcGiSubEntityTraits:: setFillType () был установлен, это, режим Fill используется независимо от перегенерального типа.

    Типичная операция глубокого клона

    Следующая выборка кода показывает типичное использование AcDbDatabase:: deepCloneObjects ().
    Инициализировать глубокую операцию клона
    1 Получают набор объектов, которые нужно клонировать.
    2 Помещенный объектные ID в список (типа AcDbObjectIdArray).
    3 Создают новую карту ID (класса AcDbIdMapping) который будет заполнен deepCloneObjects () функция.
    4 Называют deepCloneObjects () функцией, проходящей в списке объектов, которые нужно клонировать, объект ID владельца, к которому клонированные объекты должны быть добавлены в конец, и карта ID, созданная в шаге 1.
    В этом примере, объект ID владельца - запись таблицы блоков пространства модели.
    DeepCloneObjects () функция заполняет карту объекта ID (idMap). Приложение может тогда выполнять итерации через объекты, содержащиеся в карте, используя специальный iterator объект (AcDbIdMappingIter) и исполнять дополнительные операции на тех объектах, типа преобразования каждого объекта некоторой матрицей.
    Следующий код показывает типичное использование deepCloneObjects ():
    void
    cloneSameOwnerObjects()
    {
    // Step 1: Obtain the set of objects to be cloned.
    ads_name sset;
    if (acedSSGet(NULL, NULL, NULL, NULL, sset) != RTNORM) {
    acutPrintf("\nNothing selected");
    return;
    }
    // Step 2: Add obtained object IDs to list of objects
    // to be cloned.
    long length;
    acedSSLength(sset, &length);
    AcDbObjectIdArray objList;
    AcDbObjectId ownerId = AcDbObjectId::kNull;
    for (int i = 0; i < length; i++) {
    ads_name ent;
    acedSSName(sset, 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)
    objList.append(objId);
    else if (i == 0) {
    ownerId = pObj->ownerId();
    objList.append(objId);
    }
    pObj->close();
    }
    acedSSFree(sset);
    // Step 3: Get the object ID of the desired owner for
    // the cloned objects. We’ll use model space for

    // this example.

    //

    AcDbBlockTable *pBlockTable;

    acdbHostApplicationServices()->workingDatabase()

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

    AcDbObjectId modelSpaceId;

    pBlockTable->getAt(ACDB_MODEL_SPACE, modelSpaceId);

    pBlockTable->close();

    // Step 4: Create a new ID map.

    //

    AcDbIdMapping idMap;

    // Step 5: Call deepCloneObjects().

    //

    acdbHostApplicationServices()->workingDatabase()

    ->deepCloneObjects(objList, modelSpaceId, 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());

    }

    }

    Типовое ObjectARX-приложение

    Сравните типовые приложения программ факториала, распределенных с AutoCAD. Программа fact.ccp - для среды программы ObjectARX, в то время как fact.c - для среды программы ADS. Следующая версия fact.cpp объявляет и осуществляет acrxEntryPoint (); иначе, fact.cpp почти идентичен fact.c. Функция acrxEntryPoint () заменяет главное в fact.c:
    #include
    #include "adslib.h"
    #include "rxdefs.h"
    // Utility definition to get an array’s element count (at compile
    // time). For example:
    //
    // int arr[] = {1,2,3,4,5};
    // ...
    // printf("%d", ELEMENTS(arr));
    //
    // would print a five. ELEMENTS("abc") can also be used to tell
    // how many bytes are in a string constant INCLUDING THE TRAILING
    // NULL.
    #define ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
    // All the functions that we’ll define will be listed in a single
    // table, together with the internal function that we call to handle
    // each. The functions all take a single argument (the resbuf that
    // has the arguments) and return an integer (RTNORM or RTERROR for
    // good or bad status).
    // First, define the structure of the table: a string giving the
    // AutoCAD name of the function, and a pointer to a function
    // returning type int.
    struct func_entry {
    char *func_name;
    int (*func) _((struct resbuf *));
    };
    // Here we declare the functions that handle the calls; at the moment
    // there are two of them.
    int fact _((struct resbuf *rb));
    int squareroot _((struct resbuf *rb));
    // Here we define the array of function names and handlers.
    static struct func_entry func_table[] = {
    {/*MSG0*/"fact", fact},
    {/*MSG0*/"sqr", squareroot},
    };
    // To add more functions to this table, just put them in the list,
    // after declaring the function names. Note that in standard C it’s
    // all right to have a superfluous comma after the last item.
    // The code from here to the end of dofun() is UNCHANGED when you

    // add or delete functions.

    // Declarations of other local functions:

    void main _((int, char **));

    int dofun _((void));

    int funcload _((void));

    ads_real rfact _((int x));

    ads_real rsqr _((ads_real x));

    // ACRXENTRYPOINT -- This function replaces main() for an ObjectARX

    // program.

    extern "C" AcRx::AppRetCode

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

    {

    switch(msg) {

    case AcRx::kInitAppMsg:

    acrxUnlockApplication(ptr);

    break;

    case AcRx::kInvkSubrMsg:

    dofun();

    break;

    case AcRx::kLoadADSMsg:

    funcload();

    }

    return AcRx::kRetOK;

    }

    // FUNCLOAD -- Define this application’s external functions.

    // Return RTERROR on error, else RTNORM.

    static int funcload()

    {

    int i;

    for (i = 0; i < ELEMENTS(func_table); i++) {

    if (!acedDefun(func_table[i].func_name, (short)i))

    return RTERROR;

    }

    return RTNORM;

    }

    // DOFUN -- Execute external function (called upon an RQSUBR

    // request). Return value from the function executed, RTNORM

    // or RTERROR.

    static int dofun()

    {

    struct resbuf *rb;

    int val;

    // Get the function code and check that it’s within range.

    // (It can’t fail to be, but paranoia doesn’t hurt.)

    if ((val = acedGetFunCode()) < 0 || val >= ELEMENTS(func_table))

    {

    acdbFail(/*MSG2*/"Received nonexistent function code.");

    return RTERROR;

    }

    // Fetch the arguments, if any.

    rb = acedGetArgs();

    // Call the handler and return its success-failure status.

    val = (*func_table[val].func)(rb);

    acutRelRb(rb);

    return val;

    }

    // The code from the beginning of main() to here is UNCHANGED when

    // you add or delete functions.

    // FACT -- First set up the argument, then call the factorial

    // function.

    static int

    fact(struct resbuf *rb)

    {

    int x;

    if (rb == NULL)

    return RTERROR;

    if (rb->restype == RTSHORT) {

    x = rb->resval.rint; // Save in local variable

    } else {

    acdbFail(/*MSG3*/"Argument should be an integer.");

    return RTERROR;

    }

    if (x < 0) { // Check argument range


    acdbFail(/*MSG4*/"Argument should be positive.");

    return RTERROR;

    } else if (x > 170) { // Avoid floating-point overflow

    acdbFail(/*MSG5*/" Argument should be 170 or less.");

    return RTERROR;

    }

    acedRetReal(rfact(x)); // Call the function itself, and

    // return the value to AutoLISP

    return RTNORM;

    }

    // This is the implementation of the actual external factorial

    // function.

    static ads_real rfact(int n)

    {

    ads_real ans = 1.0;

    while (n)

    ans *= n--;

    return ans;

    }

    // SQUAREROOT -- First set up the argument, then call the root

    // function.

    static int

    squareroot(struct resbuf *rb)

    {

    ads_real x;

    if (rb == NULL)

    return RTERROR; // A proper error msg would

    // be better.

    if (rb->restype == RTSHORT) { // Save in local variable.

    x = (ads_real) rb->resval.rint;

    } else if (rb->restype == RTREAL) {

    x = rb->resval.rreal; // Can accept either real

    // or integer.

    } else {

    acdbFail(

    /*MSG6*/

    "Argument should be a real or integer value.");

    return RTERROR;

    }

    if (x < 0) { // Check argument range.

    acdbFail(/*MSG7*/"Argument should be positive.");

    return RTERROR;

    }

    acedRetReal(rsqr(x)); // Call the function itself, and

    // return the value to AutoLISP.

    return RTNORM;

    }

    // This is the implementation of the actual external function

    static ads_real rsqr(ads_real x) // Square root by Newton’s  method.

    {

    int n = 50;

    ads_real y, c, cl;

    if (x == 0.0) {

    return 0.0;

    }

    y = (x * 2 + .1) / (x + 1.0);

    c = (y - x / y) / 2;

    cl= 0.0;

    while ((c != cl) && (n-- > 0)) {

    y -= c;

    cl = c;

    c = (y - x / y) / 2;

    }

    return y;

    }

    Типовой файл DCL

    Следующий DCL для создания типового диалогового окна сохранен в файле, вызвал hello.dcl:
    hello : dialog {
    label = "Sample Dialog Box";
    : text {
    label = "Hello, world";
    }
    ok_only;
    }

    Типовой Код для dwgInFields ()

    Следующее - типовой код для AsdkPoly:: dwgInFields ():
    Acad::ErrorStatus
    AsdkPoly::dwgInFields(AcDbDwgFiler* filer)
    {
    assertWriteEnabled();
    Acad::ErrorStatus es;
    if ((es = AcDbCurve::dwgInFields(filer)) != Acad::eOk)
    {
    return es;
    }
    // Object Version - must always be the first item.
    //
    Adesk::Int16 version;
    filer->readItem(&version);
    if (version > VERSION)
    return Acad::eMakeMeProxy;
    switch (version)
    {
    case 1:
    {
    AcGePoint3d center;
    filer->readPoint3d(¢er);
    AcGePoint3d startPoint;
    filer->readPoint3d(&startPoint);
    filer->readInt32(&mNumSides);
    filer->readVector3d(&mPlaneNormal);
    acutDelString(mpName);
    filer->readString(&mpName);
    filer->readHardPointerId(&mTextStyle);
    //convert data from old format
    acdbWcs2Ecs(asDblArray(center),asDblArray(center),
    asDblArray(mPlaneNormal),Adesk::kFalse);
    mCenter.set(center.x,center.y);
    mElevation = center.z;
    acdbWcs2Ecs(asDblArray(startPoint),asDblArray(startPoint),
    asDblArray(mPlaneNormal),Adesk::kFalse);
    mStartPoint.set(startPoint.x,startPoint.y);
    assert(mElevation == startPoint.z);
    break;
    }
    case 2:
    filer->readPoint2d(&mCenter);
    filer->readPoint2d(&mStartPoint);
    filer->readInt32(&mNumSides);
    filer->readVector3d(&mPlaneNormal);
    acutDelString(mpName);
    filer->readString(&mpName);
    filer->readHardPointerId(&mTextStyle);
    filer->readDouble(&mElevation);
    break;
    default:
    assert(false);
    }
    return filer->filerStatus();
    }

    Типовой Код для dwgOutFields ()

    Большинство запросов регистратора - writeItem (), функция элемента, которая была перезагружена для всех поддержанных типов данных. Имеются также другие функции, типа writeInt32 () используемый в следующем примере, который может использоваться, чтобы поддержать автоматическое приведение типа. Такие функции вынуждают параметр быть обработанными как указанный тип независимо от его фактического типа в памяти.
    ОБРАТИТЕ ВНИМАНИЕ, имеет ли ваш класс целочисленные компоненты данных, Вы должны использовать чтение и функции записи, которые явно заявляют целочисленный размер (например, writeInt32).
    Следующее - типовой код от AsdkPoly:: dwgOutFields ():
    Acad::ErrorStatus
    AsdkPoly::dwgOutFields(AcDbDwgFiler* filer) const
    {
    assertReadEnabled();
    Acad::ErrorStatus es;
    if ((es = AcDbCurve::dwgOutFields(filer))   != Acad::eOk)
    {
    return es;
    }
    // Object Version - must always be the first item.
    //
    Adesk::Int16 version = VERSION;
    filer->writeItem(version);
    filer->writePoint2d(mCenter);
    filer->writePoint2d(mStartPoint);
    filer->writeInt32(mNumSides);
    filer->writeVector3d(mPlaneNormal);
    filer->writeString(mpName);
    // mTextStyle is a hard pointer id, so filing it out to
    // the purge filer (kPurgeFiler) prevents purging of
    // this object.
    //
    filer->writeHardPointerId(mTextStyle);
    filer->writeDouble(mElevation);
    return filer->filerStatus();
    }

    Типовой Код

    Этот пример создает класс, который дает возможность пользователю создать эллипс,  выбирая его среднюю точку и затем перемещая, чтобы выбрать желательную главную ось и незначительные{*младшие*} длины оси. В течение перетащенных операций, пользователь будет способен видеть то, что эллипс напоминает в любое время.
    ОБРАТИТЕ ВНИМАНИЕ, пробует ли пользователь делать незначительную{*младшую*} ось дольше чем главная ось, эллипс закончится как круг, потому что отношение{*коэффициент*} радиуса не может быть большее чем 1.0.
    class AsdkEllipseJig : public AcEdJig
    // This class allows the user to create an ellipse by
    // picking its center point and then dragging to select the
    // desired major axis and minor axis lengths. During the
    // drag operations, the user will be able to visually see
    // what the ellipse looks like at any time.
    //
    {
    public:
    AsdkEllipseJig(const AcGePoint3d&, const AcGeVector3d&);
    void doIt();
    virtual DragStatus sampler();
    virtual Adesk::Boolean update();
    virtual AcDbEntity* entity() const;
    private:
    AcDbEllipse *mpEllipse;
    AcGePoint3d mCenterPt, mAxisPt;
    AcGeVector3d mMajorAxis, mNormal;
    double mRadiusRatio;
    int mPromptCounter;
    };
    // The following defines the constructor that accepts a point to be
    // used as the centerpoint of the ellipse and the current UCS normal
    // vector to be used as the normal for the ellipse. It also
    // initializes the radius ratio to a small value so that during
    // selection of the major axis, the ellipse will appear as a line.
    // The prompt counter is also initialized to 0.
    //
    AsdkEllipseJig::AsdkEllipseJig(
    const AcGePoint3d& pt,
    const AcGeVector3d& normal)
    : mCenterPt(pt),
    mNormal(normal),
    mRadiusRatio(0.00001),
    mPromptCounter(0)
    { }
    // This function creates an AcDbEllipse object and gets the
    // jig started acquiring the necessary info to properly fill
    // it in.
    //
    void
    AsdkEllipseJig::doIt()
    {
    mpEllipse = new AcDbEllipse;
    // Get the major axis vector from the user.

    // At this time, mPromptCounter == 0.

    //

    setDispPrompt("\nEllipse major axis: ");

    AcEdJig::DragStatus stat = drag();

    // Get the ellipse’s radius ratio.

    //

    mPromptCounter++; // now == 1

    setDispPrompt("\nEllipse minor axis: ");

    stat = drag();

    // Now add the ellipse to the database’s current space.

    //

    append();

    }

    // This function is called by the drag function to

    // acquire a sample input.

    //

    AcEdJig::DragStatus

    AsdkEllipseJig::sampler()

    {

    DragStatus stat;

    setUserInputControls((UserInputControls)

    (AcEdJig::kAccept3dCoordinates

    | AcEdJig::kNoNegativeResponseAccepted

    | AcEdJig::kNoZeroResponseAccepted));

    if (mPromptCounter == 0) {

    // Aquire the major axis endpoint.

    //

    // If the newly acquired point is the same as it was

    // in the last sample, then we return kNoChange so the

    // AsdkEllipseJig::update() function will not be called

    // and the last update call will be able to finish, thus

    // allowing the ellipse to fully elaborate.

    //

    static AcGePoint3d axisPointTemp;

    stat = acquirePoint(mAxisPt, mCenterPt);

    if (axisPointTemp != mAxisPt)

    axisPointTemp = mAxisPt;

    else if (stat == AcEdJig::kNormal)

    return AcEdJig::kNoChange;

    }

    else if (mPromptCounter == 1) {

    // Aquire the distance from ellipse center to minor

    // axis endpoint. This will be used to calculate the

    // radius ratio.

    //

    // If the newly acquired distance is the same as it was

    // in the last sample, then we return kNoChange so the

    // AsdkEllipseJig::update() function will not be called

    // and the last update call will be able to finish, thus

    // allowing the ellipse to fully elaborate.

    //

    static double radiusRatioTemp = -1;

    stat = acquireDist(mRadiusRatio, mCenterPt);

    if (radiusRatioTemp != mRadiusRatio)

    radiusRatioTemp = mRadiusRatio;

    else if (stat == AcEdJig::kNormal)

    return AcEdJig::kNoChange;

    }

    return stat;

    }

    // This function is called to update the entity based on the

    // input values.

    //

    Adesk::Boolean

    AsdkEllipseJig::update()


    {

    switch (mPromptCounter) {

    case 0:

    // At this time, mAxis contains the value of one

    // endpoint of the desired major axis. The

    // AcDbEllipse class stores the major axis as the

    // vector from the center point to where the axis

    // intersects the ellipse path (such as half of the true

    // major axis), so we already have what we need.

    //

    mMajorAxis = mAxisPt - mCenterPt;

    break;

    case 1:

    // Calculate the radius ratio. mRadiusRatio

    // currently contains the distance from the ellipse

    // center to the current pointer position. This is

    // half of the actual minor axis length. Since

    // AcDbEllipse stores the major axis vector as the

    // vector from the center point to the ellipse curve

    // (half the major axis), to get the radius ratio we

    // simply divide the value currently in mRadiusRatio

    // by the length of the stored major axis vector.

    //

    mRadiusRatio = mRadiusRatio / mMajorAxis.length();

    break;

    }

    // Now update the ellipse with the latest setting.

    //

    mpEllipse->set(mCenterPt, mNormal, mMajorAxis,

    mRadiusRatio);

    return Adesk::kTrue;

    }

    // This function must be implemented to return a pointer to

    // the entity being manipulated by the jig.

    //

    AcDbEntity*

    AsdkEllipseJig::entity() const

    {

    return mpEllipse;

    }

    // This function uses the AcEdJig mechanism to create and

    // drag an ellipse entity. The creation criteria are

    // slightly different from the AutoCAD command. In this

    // case, the user selects an ellipse center point and

    // drags to visually select the major and minor axes

    // lengths. This sample is somewhat limited; if the

    // minor axis ends up longer than the major axis, then the

    // ellipse will just be round because the radius ratio

    // cannot be greater than 1.0.

    //

    void

    createEllipse()

    {

    // First, have the user select the ellipse center point.

    // We don’t use the jig for this because there is

    // nothing to see yet.

    //

    AcGePoint3d tempPt;

    struct resbuf rbFrom, rbTo;

    acedGetPoint(NULL, "\nEllipse center point: ",


    asDblArray(tempPt));

    // The point we just got is in UCS coordinates, but

    // AcDbEllipse works in WCS, so convert the point.

    //

    rbFrom.restype = RTSHORT;

    rbFrom.resval.rint = 1; // from UCS

    rbTo.restype = RTSHORT;

    rbTo.resval.rint = 0; // to WCS

    acedTrans(asDblArray(tempPt), &rbFrom, &rbTo,

    Adesk::kFalse, asDblArray(tempPt));

    // Now you need to get the current UCS z-Axis to be used

    // as the normal vector for the ellipse.

    //

    AcGeVector3d x =

    acdbHostApplicationServices()->workingDatabase()->ucsxdir();

    AcGeVector3d y =

    acdbHostApplicationServices()->workingDatabase()->ucsydir();

    AcGeVector3d normalVec = x.crossProduct(y);

    normalVec.normalize();

    // Create an AsdkEllipseJig object passing in the

    // center point just selected by the user and the normal

    // vector just calculated.

    //

    AsdkEllipseJig *pJig

    = new AsdkEllipseJig(tempPt, normalVec);

    // Now start up the jig to interactively get the major

    // and minor axes lengths.

    //

    pJig->doIt();

    // Now delete the jig object, since it is no longer needed.

    //

    delete pJig;

    }

    void

    initApp()

    {

    acedRegCmds->addCommand("ASDK_VISUAL_ELLIPSE",

    "ASDK_VELLIPSE", "VELLIPSE", ACRX_CMD_MODAL,

    createEllipse);

    }

    void

    unloadApp()

    {

    acedRegCmds->removeGroup("ASDK_VISUAL_ELLIPSE");

    }

    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();

    }

    return AcRx::kRetOK;

    }

     Типы Курсора

    Если Вы хотите установить специальный тип курсора, используйте следующую функцию:
    void
    AcEdJig::setSpecialCursorType(AcEdJig::CursorType);
    CursorType может быть одно из значений в следующей таблице:

    Курсор
    Описание
    KCrosshair
    Перекрестия, выровненные с системой координат пользователя (ВЕРХНИЕ РЕГИСТРЫ)
    kRectCursor
    Прямоугольный курсор окна, выровненный с системой координат дисплея
    KRubberBand
    Тот же самый как kCrosshair, кроме также отображает резиновую полосу от арифметической запятой
    kTargetBox
    OSNAP курсор; подобный kEntitySelect курсору, кроме его размера управляется переменной системы $APERTURE
    kCrosshairNoRotate
    Перекрестия, выровненные с системой координат дисплея
    KInvisible
    Никакая графика курсора; только графика объекта отображена
    kEntitySelect
    Одиночное поле указки объекта; объект фактически не выбран в этом случае{*регистре*}. Выбор Примитива обработан с acedSSGet ()
    KParallelogram
    Прямоугольник, выровненный с ВЕРХНИМИ РЕГИСТРАМИ (может быть параллелограмм на дисплее)
    kEntitySelectNoPersp
    Тот же самый как kEntitySelect, кроме поля указки подавлен в перспективном представлении{*виде*}; использованный, когда точный геометрический пункт{*точка*} необходим наряду с выбранным объектом
    KPkfirstOrGrips
    Заданный по умолчанию курсор; что курсор напоминает “между” командами
    kArrow
    Отображает курсор стрелки, используемый для диалоговых окон в AutoCAD

    Этот шаг необязательный. AcquirePoint () функции позволяют Вам определять этот дополнительный курсор. При установке типа курсора для acquireDist () и acquireAngle () функции не имеют никакого эффекта. AcquireXXX () функции выберут курсор для Вас, если Вы явно не определяете тот.

    Типы Объектных Реакторов

    Реакторные классы, показанные выше также упомянуты как переходные реакторные классы. Если Вы хотите, чтобы ваша программа получила уведомление события, вы будете обычно использовать переходные реакторы, которые контролируют события, которые случаются с объектами базы данных. Они могут также контролировать события базы данных, взаимодействие пользователя, и другие события системы, в то время как приложение выполняется.
    Другой вид реактора, названного постоянный реактор, использует объект базы данных (образец класса AcDbObject или полученного класса) как реактор. Объекты Базы данных могут получать также как посылать уведомление. Постоянные реакторные зависимости в пределах базы данных - часть базы данных, так что они сохраняются в DWG и DXF файлах и восстановлены, когда рисунок загружен.
    Использовать AcDbObject
    как реактор
    1 Получают новый AcDbObject класс и осуществляют функции уведомления для событий, ваш объект ответит на.
    2 Инициализируют объектный реактор.
    3 Добавляют объектный реактор к базе данных и дают этому владельца, предпочтительно контейнерный объект, так, чтобы это было зарегистрировано из правильно.
    4 Добавляют объектный реактор к реакторному списку уведомителя, используя addPersistentReactor () функция. Эта функция требует, чтобы Вы прошли в объекте ID объектного реактора, который Вы создавали в шаге 2.
    AutoCAD удалит объектный реактор, потому что это - объект базы данных.
    ОБРАТИТЕ ВНИМАНИЕ, когда Вы копируете объект, любые постоянные реакторы, приложенные к объекту скопированы также. Переходные реакторные приложения не скопированы, когда объект скопирован.

    Точки

    Точки AutoCAD определены как следующий тип массива:
    typedef ads_real ads_point [3];
    Точка всегда включает три значения. Если точка двумерна, третий элемент массива может игнорироваться; самое безопасное инициализировать это к 0.
    ObjectARX
    определяет следующие значения точки:
     
    #define X 0
    #define Y 1
    #define Z 2
    В отличие от простых типов данных (или списки точки в AutoLISP), точка не может быть назначена с единственной{*отдельной*} инструкцией. Чтобы назначать указатель, Вы должны копировать индивидуальные элементы массива, как показано в следующем примере:
    newpt [X] = oldpt [X];
    newpt [Y] = oldpt [Y];
    newpt [Z] = oldpt [Z];
    Вы можете также копировать значение точки с ads_point_set () макрокоманда. Результат - второй параметр к макрокоманде.
    Следующие типовые кодовые наборы точка, чтобы равняться к сути от:
    ads_point to, from;
    from[X] = from[Y] = 5.0; from[Z] = 0.0;
    ads_point_set(from, to);
    ОБРАТИТЕ ВНИМАНИЕ на макрокоманду This, подобно ads_name_set () макрокоманда, определен по-другому, в зависимости от того, действительно ли символ __ STDC __ (для стандарта C) определен.
    Стандартная версия C ads_point_set () требует, чтобы ваша программа включила string.h.
    Из-за соглашений передачи параметров языка C, точки пропускает ссылка без адреса оператор (косвенности) и. (C всегда передает параметры массива ссылкой, с указателем на первый элемент массива.)
    AcedOsnap () библиотечная функция берет точку как параметр, и возвращает точку в результате. Это объявлено следующим образом:
    int acedOsnap(pt, mode, result)
    ads_point pt;
    char *mode;
    ads_point result;
    AcedOsnap () функция ведет себя подобно AutoLISP osnap функция. Требуется точка (запятая) и некоторые режимы объектной привязки (указанный в строковом режиме), и возвращает самую близкую точку (в результате). Значение int, что acedOsnap () возвращения - код состояния, который указывает успех (RTNORM) или отказ{*неудачу*}.
    Следующий кодовый фрагмент вызывает acedOsnap ():
    int findendpoint(ads_point oldpt, ads_point newpt)
    {
    ads_point ptres;
    int foundpt;
    foundpt = acedOsnap(oldpt, "end", ptres);
    if (foundpt == RTNORM) {
    ads_point_set(ptres, newpt);
    }
    return foundpt;
    }
    Поскольку точки - массивы, oldpt и ptres автоматически проходят к acedOsnap () ссылкой (то есть как указатели на первый элемент каждого массива) скорее чем значением. AcedOsnap () функция возвращает ее результат (в противоположность ее состоянию) устанавливая значение newpt параметра.
    ObjectARX
    определяет указатель на точку, когда указатель необходим вместо типа массива.
    typedef ads_real *ads_pointp;

    Топологические Объекты

    Топологические объекты являются или первичными или вторичными, в зависимости от того, связаны ли они к определенному топологическому измерению.
    Первичные топологические объекты используются, чтобы охватить оцененное пространство модели полностью. Они определены в терминах точечных множеств и также упомянуты как n-simplexes, где n - их топологическое измерение. 0-симплексная часть - вершина, 1-симплексная часть - край, 2-симплексная часть - лицо, и 3-симплексная часть - комплекс.
    Они не включают их границы, но они могут быть ограничены симплексами любого более низкого измерения.
    Первичные топологические объекты - следующее:


    Комплекс

    Связанный топологически трехмерная область{*регион*} точек R 3 в E 3. Это - объем, созданный вне вершины, лиц, и граней. Комплекс обычно ограничивается одним или большее количество оболочек.

    Лицо

    Связанный топологически двумерная область{*регион*} точек R 2 в E 3. Это ограничено, orientable подмножество поверхности на границе оболочки комплекса. Лицо обычно ограничивается одним или большее количество циклов.

    Край

    Связанный топологически одномерная область{*регион*} точек R 1 в E 3. Это ограничено, orientable подмножество кривой на границе цикла лица. Край обычно ограничивается одной или двумя вершиной.

    Вершина

    Связанный топологически нульмерная область{*регион*} точек R 0 в E 3. Это - единственная точка на лице. Вершина ограничена только отдельно.

    Геометрии, возвращенной каждым из этих первичных топологических объектов можно делать запрос, далее используя Библиотеку Геометрии Autodesk.
    Вторичные топологические объекты - связанные коллекции первичных топологических объектов, и не обязательно связаны к определенному топологическому измерению. Они представляют отображение границы от симплекса с  более высоким измерением до набора симплексов с  более низким измерением, которые определяют связанную часть его границы. Каждый первичный топологический объект принадлежит по крайней мере одному вторичному топологическому объекту.

    Вторичные топологические объекты - следующее:



    Brep



    Коллекция всего в оцененном пространстве{*пробеле*}; то есть коллекция всех первичных и других связанных вторичных топологических объектов для уникального E 3. По крайней мере, эта коллекция должна содержать единственный комплекс.



    Оболочка

    (Shell)



    Неупорядоченная коллекция лиц, которые ограничили комплекс. По крайней мере, эта коллекция должна содержать единственное лицо. Может иметься самое большее одна внешняя оболочка, и должна иметься внешняя оболочка для там, чтобы быть внутренними оболочками (voids).



    Цикл

    (LOOP)



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


    Traverser Классы

    Traverser объекты типично формируются, используя по умолчанию AcBrTraverser* конструктор и затем инициализируя с одной из функций set*. Обратите внимание, что владелец списка должен быть установлен прежде, чем позиция списка может быть установлена независимо, обеспечивать контекст.
    Все классы, полученные из AcBrTraverser поддерживают конструкторы копии, операторы назначения, isEqualTo (), и isNull (), наряду с общими функциями обхода.
    Функции инициализатора семантически связаны к типам AcBr, соответствующим к определенному traverser (то есть два типа, содержащиеся в полученном traverser имени класса, типа AcBrBrep и AcBrEdge для AcBrBrepEdgeTraverser).
    Все функции инициализатора сбрасывают критерии для следующего () и сделанного (). Они относятся к общим алгоритмическим категориям следующим образом:
    § setListOwnerAndCurrentPosition от другого traverser, используя его владельца списка как текущая позиция и его текущая позиция, поскольку владелец списка (то есть меняет владельца списка и текущую позицию). Этот алгоритм только имеет силу для отображения между связанным traversers типа AcBrLoopEdgeTraverser и AcBrEdgeLoopTraverser.
    § setListOwnerAndCurrentPosition от объекта AcBr, используя это как текущая позиция и ее владелец как владелец списка. Этот алгоритм только имеет силу в случаях, где владелец списка однозначен, типа владельца оболочки лица при установке AcBrShellFaceTraverser.
    § setListOwner от другого traverser, используя его текущую позицию как владелец списка и defaulting текущая позиция к первой позиции в новом списке смежных вершин. Этот алгоритм только имеет силу для установки вниз иерархический traversers использование другого убывающего иерархического traverser от следующего уровня (типа использования AcBrShellFaceTraverser, чтобы инициализировать AcBrFaceLoopTraverser), или для установки вверх иерархический traversers использование другого восходящего иерархического traverser от следующего уровня вниз (типа использования AcBrVertexEdgeTraverser, чтобы инициализировать AcBrEdgeLoopTraverser).

    § setListOwner от объекта AcBr, используя это как владелец списка и по умолчанию - ing текущая позиция к первой позиции в новом списке смежных вершин. Этот алгоритм имеет силу для всех типов traverser.

    § setCurrentPosition от объекта AcBr, используя это как текущая позиция в уже установленном списке. Этот алгоритм имеет силу для большинства traverser, напечатает, но требует, чтобы владелец списка уже был установлен предварительно.

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

    § AcBrTraverser

    § AcBrBrepComplexTraverser

    § AcBrBrepShellTraverser

    § AcBrBrepFaceTraverser

    § AcBrBrepEdgeTraverser

    § AcBrBrepVertexTraverser

    § AcBrComplexShellTraverser

    § AcBrShellFaceTraverser

    § AcBrFaceLoopTraverser

    § AcBrLoopEdgeTraverser

    § AcBrLoopVertexTraverser

    § AcBrVertexLoopTraverser

    § AcBrVertexEdgeTraverser

    § AcBrEdgeLoopTraverser

    § AcBrMesh2dElement2dTraverser

    § AcBrElement2dNodeTraverser

    TrueType Разработка Шрифта

    Хотя ни SimpleView ни WhipView, через AcGix, не поддерживает TrueType шрифты, имеется процедура, доступная в ObjectDBX для тех, кто хотят пробовать добавить TrueType поддержку шрифта на их собственный. Механизм - textMsg () метод AcGixVectorTaker класса.
    Когда объект текста TrueType должен быть отображен, AcGix вызывает textMsg () методом vectortaker. В этой точке vectortaker выполнение может или обрабатывать текст или возвращать Adesk:: kFalse, чтобы инструктировать AcGix исполнять его обработку по умолчанию, которая должна преобразовать текст в SHX шрифт (txt.shx по умолчанию) и затем исполнять стандарт SHX обработка.
    Координаты, снабженные textMsg () находятся в текущих образцовых координатах.
    Они могут быть преобразованы к Мировой системе координат (WCS), использование снабженного преобразовывает.
    Задача представления TrueType шрифты в трехмерном пространстве сложна, и это осуществление рекомендуется только для тех смотрящий достичь полной совместимости дисплея AutoCAD. Один подход может быть только, чтобы обработать это сообщение, если текст может быть представлен в виде плана для вашей области просмотра, и иначе использовать заданную по умолчанию обработку.
    TextMsg () метод определен в AcGixVectorTaker.h:
    virtual Adesk::Boolean
    textMsg(
    Adesk::Int16 nViewportId,
    const TextPacket * pPacket) = 0;
    Структура TextPacket содержит информацию относительно текста плюс матрица преобразования, имел обыкновение преобразовывать от текущей модели до WCS.
    struct TextPacket
    {
    TextPacket(
    const TextInfo* pInfo,
    int nColor,
    const AcGeMatrix3d& xModel);
    int m_nColor;
    const TextInfo* m_pInfo;
    const AcGeMatrix3d& m_xCurrentModelToWorld;
    };
    Структура TextInfo содержит всю информацию относительно текста:
    struct TextInfo
    {
    AcGePoint3d m_Position;
    AcGeVector3d m_Normal;
    AcGeVector3d m_Direction;
    double m_Height;
    double m_Width;
    double m_Oblique;
    const char* m_pMsg;
    Adesk::Int32 m_Length;
    Adesk::Boolean m_Raw;
    double m_Thickness;
    const AcGiTextStyle * m_pTextStyle;
    };

    Undo базы данных и средства управления транзакции

    Большинство ObjectARX-приложений не будет должно иметь дело с отменой и операционным управлением, но они должны знать некоторые важные точки:
    § Отмена и операционное управление выполнен на основании "в документ ". В AutoCAD, это управляется через (или в конъюнкции с) блокировкой документа.
    § Всякий раз, когда документы блокированы для kWrite или kXWrite, “начинают команда” скобка отмены написана к файлу, и затем база данных и другие модификации выполнена. Когда документы разблокированы от kWrite или kXWrite состояния, передача “конечная команда” скобка отмены будет написана. (Обратите внимание, что они могут быть вложены.) К времени приложение закончено, работая на документе, это должно было сбалансировать, его документ блокирует и разблокирует запросы. Если запросы не сбалансированы, файл отмены будет работать неправильно, оставляя действия из sync от после первой блокировки записи, и через первую блокировку, сбалансированную разблокирующимся. Последующий запрос отмены должен отложить это в sync.
    § параметр для установления имени команды обеспечивается, который отображен, когда команда UNDO выполнена. Созданные маркеры отмены - тот же самый что касается встроенного AutoCAD и команд ObjectARX, и могут поэтому управляться через ГРУППУ ОТМЕН.
    § Документы может иметь отмену, выполненную независимо от друг друга.
    § По умолчанию, когда образец AcDbDatabase создан, его отмена и операционное управление связана с текущим документом.
    § Обращают внимание, что имеются два метода AcEditorReactor, которые используются, чтобы соединить базы данных со средствами отмены документа и операционным менеджером: databaseConstructed() и databaseToBeDestroyed(). Если Вы получаете такое уведомление, знаете, что ассоциация между базой данных и любыми документами неопределена в ту временами, так документ, блокировка может или не может треб в databaseConstructed () повторный вызов. Конечно, любое действие, которое отменяет любые модификации, сделанные в то время,  также отменит создание базы данных.
    § по умолчанию AcDbDatabase конструкторы сделает запрос объекта AcDbHostApplicationServices для контроллера отмены.

    Управление памятью Буфера результата

    Основное различие между списками буфера результата и сопоставимыми списками результата AutoLISP - то, что ObjectARX-приложение должно явно управлять списками, которые это создает и использования. Создает ли приложение список или имеет тот, пропускал к этому, это - ответственность приложения выпустить буфера результатов, которые это размещает. ObjectARX не имеет никакой автоматической сборки "мусора", поскольку AutoLISP делает. Приложение должно вызвать библиотечную функцию acutRelRb () чтобы выпустить динамически размещенные буфера результатов, когда приложение закончено с ними.
    AcutRelRb () функция выпускает полный список, который следует за указанным буфером результатов, включая указанный (главный) буфер, непосредственно и любая строка оценивает это буфера в точке списка к. Чтобы выпускать строку без того, чтобы удалить буфер непосредственно, или выпускать строку, принадлежащую на статический буфер результатов, приложение должно вызвать функцию стандартной библиотеки C free().
    ПРЕДУПРЕЖДЕНИЕ! Не запишите данные к динамическому местоположению, которое не было размещено с прямым, вызывает к malloc () или с ObjectARX библиотекой (включая acutNewRb ()). Это может разрушать данные в памяти. Наоборот, вызывая free() или acutRelRb() чтобы выпустить данные, который был размещен статически — в статическом или объявлении — динамической локальной переменной также, может разрушать память. Вставка статически размещенной переменной, типа строки, в список буфера результата заставляет вашу программу терпеть неудачу, когда Вы выпускаете список с acutRelRb ().
    Выборка вызывает к acutRelRb() появляются в нескольких из примеров кода в следующих секциях.

    Управление ресурсами

    Управление ресурсами - важное соображение{*рассмотрение*} при проектировании Приложения ObjectArx, которое использует MFC
    библиотеку, общедоступную с AutoCAD и другими приложениями.
    Вы должны вставить ваше состояние модуля (использование CDynaLinkLibrary) в цепочку, которую MFC исследует, когда это исполняет операции типа расположения ресурса.
    Однако, строго рекомендуется, чтобы Вы явно управляли ресурсами вашего приложения так, чтобы они не нашлись в противоречии с другими ресурсами от AutoCAD или других Приложений ObjectArx.
    Явно устанавливать ресурсы
    1 Перед взятием любых шагов, которые вызвали бы MFC, чтобы искать ваш ресурс, вызывают функцию AFX AfxSetResourceHandle() чтобы установить заказной ресурс как системное значение по умолчанию.
    2 Перед установкой системного ресурса к вашему ресурсу, вызовите AfxGetResourceHandle() чтобы получить текущий системный ресурс.
    3 Немедленно после выполнения любых функций, которые требуют,  заказной ресурс, системный ресурс должен быть сброшен к маркеру{*дескриптору*} ресурса, предварительно сохраненному.
    Запрос функций API AutoCAD (или при вызове команд AutoCAD) внутри диалога командует обработчиком, который нуждается в ресурсах AutoCAD, типа acedGetFileD (), задерживает ресурс к AutoCAD перед запросом функций.
    Восстановите ваш прикладной ресурс впоследствии. (Используйте acedGetAcadResourceInstance () чтобы получить маркер{*дескриптор*} ресурса AutoCAD.)

     Уровень Примитива

    Все примитивы имеют связанный уровень. База данных всегда содержит по крайней мере один уровень (уровень 0). Как с linetypes, Вы можете определить уровень для примитива. Если Вы не определяете уровень, заданное по умолчанию значение уровня базы данных используется для нового примитива.
    Каждый уровень также связал свойства, которые включают замораживающийся / таял, вкл\выкл, блокируемый / разблокир, цвет, linetype, и область просмотра (см. главу 7, “ Контейнерные Объекты ”). Когда цвет примитива или linetype - BYLAYER, значение свойства уровня используется для примитива.
    Если значение уровня определено для примитива, текущее значение уровня базы данных игнорируется.
    Следующие функции дают возможность Вам установить уровень для примитива, или по имени или объектом ID:
    Acad::ErrorStatus
    AcDbEntity::setLayer(const char* newVal);
    Acad::ErrorStatus
    AcDbEntity::setLayer(AcDbObjectId newVal);
    Эта функция возвращает название{*имя*} текущего уровня примитива:
    char* AcDbEntity::layer() const;
    Эта функция возвращает объект ID для текущего уровня (объект типа AcDbLayerTableRecord):
    AcDbObjectId AcDbEntity::layerId() const;

    Уровни Совместимости

    Ваше ObjectARX-приложение может иметь один из четырех уровней совместимости с MDI:
    § SDI-ТОЛЬКО
    § MDI-ЗНАЮЩИЙ
    § MDI-СПОСОБНЫЙ
    § MDI-РАСШИРЕННЫЙ
    SDI-ТОЛЬКО - минимальное требование, но MDI-СПОСОБНАЯ совместимость рекомендуется.
    MDI поддерживает контекст выполнения в документ и обеспечивает средство для разрешения единственного контекста выполнения, чтобы быть активным при переключении документов.

    Условная Фильтрация

    Относительные операторы, только описанные - двоичные операторы. Вы можете также проверять группы,  создавая вложенные выражения Boolean те операторы условного выражения использования. Условные операторы также определены -4 группами, но они должны быть соединены.
    Следующий типовой код выбирает все круги в рисунке к радиусу 1.0 и всем линиям на уровне “ABC”.
    eb1 = acutBuildList(-4, " "CIRCLE", 40, 1.0, -4, "and>", -4, " "LINE", 8, "ABC", -4, "and>", -4, "or>", 0);
    acedSSGet("X", NULL, NULL, &eb1, ssname1);
    Условные операторы не чувствительны к регистру; Вы можете использовать эквиваленты нижнего регистра.
    ОБРАТИТЕ ВНИМАНИЕ на выражения Conditional, которые проверяют на расширенные данные, использующие -3 группа, может содержать только -3 группы. См. “ Фильтрующий для Расширенных Данных ” на странице 206.
    К выделите всё кругам, которые расширили{*продлили*} данные, зарегистрированные или на “APP1” или “APP2”, но не оба, Вы могли использовать следующий код.

    eb1 = acutBuildList(-4, "", 0);
    acedSSGet("X", NULL, NULL, &eb1, ssname1);

    Установка Черт Примитива

    Имеются три уровня, от которых цвет примитива, уровень, и значения linetype может быть установлен: drawable уровень, уровень подпримитивов, и подпримитивный уровень. Другие черты могут сходим только один или два из уровней:
    §
    Drawable уровень. Выполнение setAttributes () определяет, что  заданные по умолчанию черты для примитивов имели обыкновение отображать drawable. Для большинства примитивов, полный объект представлен, используя текущие свойства примитива: linetype, цвет, уровень, и так далее.
    § Subentity Level (Уровень Подпримитивов). Вы можете определить определенные черты, которые нужно использовать для определенных частей drawable в течение worldDraw () или viewportDraw () выполнение. Вы можете использовать интерфейс AcGiSubEntityTraits, чтобы перегрузить черты, которые были определены в setAttributes () запрос. Как только значение для черты установлено, это используется для всех последующих примитивов до конца метода или пока новое значение определено.
    ОБРАТИТЕ ВНИМАНИЕ В этой главе, подпримитив термина используется по-другому чем в главе 6, “примитивах”, где термин относится к определенным геометрическим частям примитива. В этой главе, подпримитив - не часть примитива; это - только уровень, на котором значения черты могут быть установлены и изменен.
    § Subprimitive Level  Функции примитива оболочки имеют необязательные параметры, которые позволяют Вам определять богатый набор черт на "в край" и основание "в лицо". (См. примеры кода в “Примитивах” на странице 696.) Для любой черты, этот механизм требует, чтобы Вы установили значения для всех граней или лиц, или для ни одного из них. Вы устанавливаете только черты, которые Вы хотите. Например, Вы можете устанавливать цвета граней оболочки или поймать в сети без того, чтобы иметь необходимость устанавливать уровни или linetypes, но Вы должны определить цвет для каждого края. В добавлении, чтобы поймать в сети и черты подпримитива оболочки, имеется версия текстовой примитивной функции, которая имеет текстовый параметр стиля. Текстовый стиль может быть установлен только при подпримитиве (примитив " в текст ") уровень. Подпримитивные значения черты заменяют значения соответствующего набора черт в уровнях drawable и подпримитиве.

    Установка текущего документа без его активации

    Имеются несколько особенностей, которые неявно работают на текущем документе, который может отличаться от активного документа. Вы можете использовать функцию AcApDocManager:: setCurDocument () с активизирующимся набором параметров к kFalse, чтобы делать текущий документ и активный отличный документ. Особенности,  которых это является необходимым, включают:
  • Использование любых функций взаимодействия пользователя, типа acedXXX () функции.

  • Создание базы данных, которая будет связана со специфическим документом.

  • Получение или управление набором выборов без того, чтобы требовать взаимодействие пользователя.

  • функции Using, описанные в aced.h.

  • Когда активный и текущий документы различны, все функции ввода пользователя и члены относительно документа, типа графического экрана, будут заблокированы. Это включает функции для обоих приложений ObjectARX и ActiveX.
    Всякий раз, когда Вы устанавливаете текущий документ без также формирования этого, setCurDocument () вызывающая программа должна восстановить текущий документ, чтобы быть тем же самый как активный документ когда закончено. Однако, если это не сделано к времени, что следующий входной случай обработан, текущий документ будет переключен назад к активному документу.

    Установка версии как SHAREDFILE

    Весь DLLS Autodesk обеспечивает, содержат ресурс версии. При установке этих файлов Вы должны определить, что они, быть модифицировано только, если версия равна или большая чем те которые могут существовать на машине пользователя. InstallShield обеспечивает пару способов делать это использование комбинация ФЛАЖКОВ COMP_UPDATE_VERSION и COMP_UPDATE_SAME.
    Кроме того Вы должны также отметить эти файлы с флажком SHAREDFILE при установке. Это будет гарантировать, что Вы поддерживаете подсчет ссылки к другим прикладным инсталляторам, которые могут устанавливать и использование этих библиотек и файлов.
    Следующий сценарий InstallShield - пример, который устанавливает acge15.dll использование версия и общедоступный механизм файла.
    TARGETDIR = COMMONFILES ^ "Autodesk Shared";
    nReturn = XCopyFile (
    "acge15.dll", "acge15.dll",
    COMP_UPDATE_SAME |
    COMP_UPDATE_VERSION |
    SHAREDFILE);
    if (nReturn < 0 ) then
    // Report failure
    endif;

    Установка Заданного по умолчанию Формата файла

    ObjectARX обеспечивает способность определить заданный по умолчанию формат файла для SAVEAS, SAVE и команд QSAVE. (Команда AUTOSAVE всегда сохраняет рисунки в формате чертежного файла AutoCAD 2000.)
    Класс AcApDocument содержит перечисление, которое определяет формат, используемый при сохранении рисунка к файлу. Его значения показываются в следующей таблице:

    Name
    Usage (file extension)
    kR12_dxf
    AutoCAD Release 12/LT2 DXF (*.dxf)
    kR13_dwg
    AutoCAD Release 13/LT95 Drawing (*.dwg)
    kR13_dxf
    AutoCAD Release 13/LT95 DXF (*.dxf)
    kR14_dwg
    AutoCAD Release 14/LT97 Drawing (*.dwg)
    kR14_dxf
    AutoCAD Release 14/LT97 DXF (*.dxf)
    kR15_dwg
    AutoCAD 2000 Drawing (*.dwg)
    kR15_dxf
    AutoCAD 2000 DXF (*.dxf)
    kR15_Template
    AutoCAD 2000 Drawing Template File (*.dwt)
    kNative
    Current DWG version is AutoCAD 2000
    kUnknown
    Invalid format

    AcApDocument:: formatForSave () функция возвращается,  поток{*ток*} сохраняет{*экономит*} формат,  используемый SAVEAS, СОХРАНЯЕТ{*ЭКОНОМИТ*}, и командами QSAVE:
    AcApDocument:: SaveFormat
    FormatForSave ();
    Возвращенное значение может быть или сеанс-широкая настройка по умолчанию, или различная установка, которую пользователь выбрал для этого документа. Если это - перегрузка для этого документа, это не будет упорствовать{*сохраняться*} поперек сеансов.
    AcApDocmanager:: setDefaultFormatForSave () функция использует одно из значений SaveFormat, чтобы заставить формат файла использовать при сохранении рисунка к SAVEAS, СОХРАНЯТЬ{*ЭКОНОМИТЬ*}, и командам QSAVE. Это устанавливает сеанс-широкое значение по умолчанию, которое пользователь может выбирать временно перегружать для индивидуального документа:
    Acad:: ErrorStatus
    SetDefaultFormatForSave (
    AcApDocument:: формат
    SaveFormat);
    Эти функции только непосредственно сообщают относительно или устанавливают формат файла для интерактивных команд, введенных пользователем. Если Вы хотите, чтобы ваше приложение использовало поток{*ток*}, сохраняют{*экономят*} формат, каждый раз Вы желаете сохранить{*экономить*} базу данных, Вы будете сначала должны вызвать{*назвать*} formatForSave (), и затем использовать возвращенное значение SaveFormat, чтобы определить, которые функционируют, чтобы звонить. Например, если бы formatForSave () возвратил kR14_dxf, Вы вызвали бы{*назвали бы*} acdbDxfOutAsR14 () чтобы записать базу данных как Выпуск 14 DXF файл.
    Убедитесь, что брали следующий во внимание:
    § Или Вы или ваш пользователь можете устанавливать постоянный сеанс-широкий заданный по умолчанию формат для, сохраняют{*экономят*}, который будет удостоен,  все сохраняют{*экономят*} команды кроме, АВТОСОХРАНЯЮТ{*АВТОЭКОНОМЯТ*}.
    § Только пользователь может временно (не постоянно между сеансами) перегружают эту установку для специфического документа.
    § formatForSave () метод возвращает формат, в котором пользователь желает, чтобы индивидуальный документ был сохранен; это будет или сеанс-широкое значение по умолчанию или временная перегрузка, как соответствующий.

    Вещественные числа

    Реальные значения в AutoCAD - всегда с двойной точностью с плавающей точкой значения.
    ObjectARX сохраняет этот стандарт,  определяя специальный тип ads_real, следующим образом:
    typedef double ads_real;
    Реальные значения в ObjectARX-приложении имеют тип ads_real.

    Входные Опции для Функций Ввода пользователя

    Следующая таблица суммирует служебные биты, которые могут быть определены val параметром. Чтобы устанавливать больше чем одно условие одновременно, добавьте значения вместе, чтобы создать значение val между 0 и 127. Если val установлен на нуль, ни один из условий контроля не обращается к следующему запросу функции ввода пользователя.
    ОБРАТИТЕ ВНИМАНИЕ На будущие версии AutoCAD, или ObjectARX может определять дополнительный acedInitGet () служебные биты, так что Вы должны избежать устанавливать любые биты, что не показывается в таблице или описано в этой секции.
    Входные опции, установленные acedInitGet ()

    Код
     Бит
     Описание Значения
    RSG_NONULL
     1
     Отвергают нулевой{*пустой*} ввод
    RSG_NOZERO
     2
     Отвергают нулевые значения
    RSG_NONEG
     4
     Отвергают отрицательные значения
    RSG_NOLIM
     8
     Не проверяют пределы рисунка, даже если LIMCHECK включен
    RSG_DASH
     32
     Пунктирные линии Использования при рисунке резиновой полосы выравнивают или поле
    RSG_2D
     64
     Игнорируют координату Z трехмерных точек (acedGetDist () только)
    RSG_OTHER
     128
     Позволяют произвольный ввод — вводит ли пользователь

    Следующая выборка программы показывает использование acedInitGet() чтобы основать запрос к acedGetInt () функция.
    int age;
    acedInitGet(RSG_NONULL | RSG_NOZERO | RSG_NONEG, NULL);
    acedGetInt("How old are you? ", &age);
    Эта последовательность спрашивает возраст пользователя. AutoCAD автоматически отображает сообщение об ошибках и повторяет подсказку, если пользователь пробует вводить отрицательное или нулевое значение, нажмите ENTER только, или введите ключевое слово. (Сам AutoCAD отклоняет попытки ввести значение, которое - не целое число.)
    Опция RSG_OTHER позволяет следующему запросу функции ввода пользователя принять произвольный ввод. Если RSG_OTHER установлен, и пользователь вводит непризнанное значение, acedGetxxx () функциональные возвращения RTKWORD, и ввод могут быть восстановлены{*отысканы*} запросом к acedGetInput (). Поскольку конечный пользователь пространств{*пробелов*} вводит также, как ВВОДЯТ, делает, произвольный ввод никогда не содержит пространство{*пробел*}. Опция RSG_OTHER имеет самый низкий приоритет всех опций, перечисленных в предшествующей таблице; если acedInitGet () запрос отверг отрицательные числа{*номера*} с RSG_NONEG, например, AutoCAD все еще отклоняет их.

    Следующий код позволяет произвольный ввод (проверка ошибок минимальна).

    int age, rc;

    char userstring[511];

    acedInitGet(RSG_NONULL | RSG_NOZERO | RSG_NONEG | RSG_OTHER, "Mine Yours");

    if ((rc = acedGetInt("How old are you? ", &age)) == RTKWORD) {

    // Keyword or arbitrary input

    acedGetInput(userstring);

    }

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

    Произвольный ввод пользователя

     Ввода пользователя

    Результат

    41

     AcedGetInt () возвращает RTNORM и устанавливает возраст в 41

    m

     AcedGetInt () возвращает RTKWORD, и acedGetInput () возвращает “Источник”

    y

     AcedGetInt () возвращает RTKWORD, и acedGetInput () “Ваши” возвращения

    Двадцать

     AcedGetInt () возвращает RTKWORD, и acedGetInput () возвращается “двадцать”

    Какой???

     AcedGetInt () возвращает RTKWORD, и acedGetInput () возвращения “ какой??? ”

    -10

     AutoCAD отклоняет этот ввод и восстанавливает изображение подсказки, поскольку RSG_NONEG установлен (другие разрядные коды имеют приоритет по RSG_OTHER)

    -34.5

     AcedGetInt () возвращает RTKWORD, и acedGetInput () возвращается ", “-34.5" AutoCAD не отклоняет это значение, потому что это ожидает целое число, не реальное значение (если бы бы это было acedGetReal () запрос, AutoCAD принял бы отрицательное целое число как произвольный ввод, но отклонил бы отрицательное реальное значение)

    ОБРАТИТЕ ВНИМАНИЕ На acedDragGen () функция указала бы произвольный ввод (если этому позволил предшествующий acedInitGet () запрос) возвращая RTSTR вместо RTKWORD.

    Видимость Примитива

    Если Вы определяете, что примитив невидим, это будет невидимо независимо от других параметров настройки в базе данных. Другие коэффициенты{*факторы*} могут также заставлять примитив быть невидимыми.
    Например, примитив не будет отображен, если его уровень выключен или закрепляется.
    Значение AcDb:: Видимость может быть или kInvisible или kVisible.
    Acad::ErrorStatus
    AcDbEntity::setVisibility(AcDb::Visibility newVal);
    AcDb::Visibility
    AcDbEntity::visibility() const;

    Видимость

    AcGiEdgeData и классы AcGiFaceData позволяют Вам определять тип видимости для граней или лиц в примитиве оболочки или сети. Должен иметься точно один вход видимости в массиве для каждого края или лица в примитиве.
    Прохождение в массиве неправильного размера вызывает непредсказуемых результатов.
    Тип видимости для граней и лиц, AcGiVisibility, может иметь одно из следующих значений:
    § kAcGiInvisible
    § kAcGiVisible
    § kAcGiSilhouette
    Если поверхность не изогнута, или край не требован для рассмотрения целей, определять kAcGiInvisible. Для жестких граней поверхностных или видимых складок, определите kAcGiVisible. Для граней или лиц, которые Вы можете видеть от некоторых точек зрения, определите kAcGiSilhouette. Тип видимости силуэта признан только командой HIDE; иначе, это интерпретируется как kAcGiVisible.
    Например, в твердом цилиндре, показанном ниже, грани, которые формируются,  оправы цилиндра - видимые грани. Грани latitudinal - невидимые грани, так как они никогда не используются для рассмотрения целей. Продольные грани - грани силуэта, так как они используются, когда цилиндр рассматривается от некоторых углов.
    Видимость

    ViewportDraw () Функция

    Если drawable возвращает ложь от worldDraw () повторный вызов, это вызывает viewportDraw () однажды для каждой активной области просмотра, чтобы позволить drawable описывать его область просмотра-определенный дисплей. AcGiViewportDraw и AcGiViewportGeometry близко связаны с worldDraw () эквиваленты, потому что они происходят от тех же самых базовых классов.
    ViewportDraw () функция работает подобным способом как worldDraw (). AcDbEntity:: viewportDraw () функция берет указатель на объект AcGiViewportDraw и формирует представление-определенное представление примитива. Область просмотра рисует объект, также обеспечивает доступ к другим объектам, которые включают следующее:
    § AcGiViewportGeometry
    § AcGiSubEntityTraits
    § AcGiViewport
    Объект геометрии области просмотра обеспечивает тот же самый список примитивов как мировой объект геометрии и добавляет к этому следующие примитивы, которые используют глаз и координаты пространства дисплея, чтобы рисовать ломаные линии и многоугольники:
    § polylineEye ()
    § polygonEye ()
    § polylineDc ()
    § polygonDc ()
    Объект черт подпримитива области просмотра - тот же самый, поскольку используемое миром рисует объект (AcGiSubEntityTraits). Объект области просмотра обеспечивает функции для запроса матриц преобразования области просмотра и рассмотрения параметров.
    ПРЕДУПРЕЖДЕНИЕ! Указатель на объект AcGi типа AcGiWorldDraw или AcGiViewportDraw не должен быть сохранен как глобальная или статическая переменная. Не сохраните копии указателей на объекты AcGi поперек, вызывает к worldDraw () и viewportDraw (). Однажды это возвращение функций, указатели больше не имеют силу.

    Вложение Диалоговых окон

    Вы создаете и управляете вложенными диалоговыми окнами просто,  вызывая ads_new_dialog () и ads_start_dialog () изнутри функции повторного вызова.
    Пользователь должен выйти из вложенного диалогового окна перед использованием предыдущего диалогового окна снова.
    AutoCAD налагает предел не больше, чем восемь вложенных диалоговых окон, но Вы не должны вложить диалоговые окна глубже чем три или четыре.
    Хотя ads_term_dialog () заканчивает все диалоговые окна сразу, это не возвращает код состояния, так не имеется никакого пути для вашего приложения, чтобы различить между сокрытием вложенного поля и отмены полей из-за условия ошибки.

    Вложение транзакций

    Транзакции могут быть вложены — то есть Вы можете запустить одну транзакцию внутри другой и заканчивать или прерывать недавнюю транзакцию. Операционный менеджер поддерживает транзакции в стеке, с самой современной транзакцией наверху стека. Когда Вы запускаете новую транзакцию, используя AcTransactionManager:: startTransaction (), новая транзакция добавлена к вершине стека, и указатель на это возвращен (образец AcTransaction). Когда кто - то вызывает AcTransactionManager:: endTransaction () или AcTransactionManager:: abortTransaction (), транзакция наверху стека закончена или прервана.
    Когда объектные указатели получены от объекта IDs, они всегда связываются с самой современной транзакцией. Вы можете получить недавнюю транзакцию, используя AcTransactionManager:: topTransaction (), затем использовать AcTransaction:: getObject () или AcTransactionManager:: getObject () чтобы получить указатель на объект. Операционный менеджер автоматически связывает объектные указатели, полученные с недавней транзакцией. Вы можете использовать AcTransaction:: getObject () только с самой современной транзакцией.
    Когда вложенные транзакции начаты, объектные указатели, полученные во внешних содержащих транзакциях также доступны для операции в самой внутренней транзакции. Если недавняя транзакция прервана, все операции, сделанные на всех объектах (связанный или с этой транзакцией или содержащими) так как начало недавней транзакции отменено, и объекты прокручены назад к состоянию в начале недавней транзакции.
    Объектные указатели, полученные в недавней транзакции прекращают иметь силу, как только это прервано.
    Если самая внутренняя транзакция закончена успешно,  вызывая AcTransactionManager:: endTransaction (), объекты, чей указатели были получены в этой транзакции, станут связанным с содержащей транзакцией и доступен для операции. Этот процесс продолжен, пока наиболее удаленная (первая) транзакция не закончена, в котором модификации времени на всех объектах совершены{*переданы*}. Если наиболее удаленная транзакция прервана, все операции на всех объектах отменены, и ничто не совершено{*передано*}.

    Внешние ссылки

    Внешние ссылки (таблицы перекрестных ссылок) могут быть созданы и управляться через несколько глобальных функций. Эти глобальные функции подражают возможностям команды XREF AutoCAD. Функции, обеспеченные
  • acedXrefAttach ()

  • acedXrefOverlay ()

  • acedXrefUnload ()

  • acedXrefDetach ()

  • acedXrefReload ()

  • acedXrefBind ()

  • acedXrefXBind ()

  • acedXrefCreateBlockname ()

  • acedXrefReload ()

  • Для информации относительно команды XREF AutoCAD, см. Руководство программиста AutoCAD.
    Главное, программирующее соображение{*рассмотрение*} относительно таблиц перекрестных ссылок - то, что, для каждой таблицы перекрестных ссылок, который приложен к рисунку, отдельная база данных создана, чтобы представить рисунок, содержащий таблицу перекрестных ссылок. Блочный отчет{*запись*} таблицы в основном рисунок содержит название{*имя*} внешнего рисунка и указывать на объекты образцового пространства{*пробела*} внешне упомянутого рисунка. База данных таблицы перекрестных ссылок также содержит другие блочные отчеты{*записи*} таблицы и входы таблицы идентификаторов, требуемые, чтобы решить все ссылки{*справочники*} от основного блочного отчета{*записи*} таблицы (уровни, linetypes, и так далее).
    Вы можете создавать редактора реактор, как описано в главе 15, “Уведомлении”, контролировать события таблицы перекрестных ссылок. AcEditorReactor класс обеспечивает следующие реакторные функции повторного вызова:
  • beginAttach ()

  • otherAttach ()

  • abortAttach ()

  • endAttach ()

  • redirected ()

  • comandeered ()

  • При использовании этих функций, будьте внимательным, чтобы обратить внимание, которая база данных возвращается. Также, знайте, что рисунок таблицы перекрестных ссылок может самостоятельно содержать таблицы перекрестных ссылок к дополнительным рисункам. Для получения дополнительной информации на AcEditorReactor классе, см. ObjectARX Ссылку{*справочники*}.
    Объекты Таблицы перекрестных ссылок в рисунке могут изменяться, но они не могут быть сохранены к первоначальному рисунку таблицы перекрестных ссылок (рисунок оригинала только для чтения).

    Внешняя ссылка Пред- и Последующая обработка

    Внешняя ссылка (таблица перекрестных ссылок) пред- и последующая обработка делает возможным восстановить приложенную таблицу перекрестных ссылок в оперативной памяти AcDbDatabase так, чтобы это могло быть сохранено назад к файлу. В течение решения таблицы перекрестных ссылок, много отчетов{*записей*} таблицы идентификаторов искарежены, и некоторые стерты. Исторически, это было сделано, чтобы упростить процесс решения, и было приемлемо, потому что базы данных были только для чтения. Эта обработка делает возможным временно полностью изменить изменения{*замены*} решения так, чтобы база данных таблицы перекрестных ссылок могла изменяться и написан назад к ее файлу.
    Функции, которые помогают в пред- и последующая обработка,  добавлены к AcDbDatabase. Они включают сервисную функцию, чтобы найти связанный блочный отчет{*запись*} таблицы от базы данных таблицы перекрестных ссылок, также как способности восстановить решенную таблицу перекрестных ссылок, и сбрасывать это назад к надлежащему решенному условию{*состоянию*} после восстановления.
    Общепринятое использование для этих функций было бы должно делать восстановление к первоначальным символам, делать модификации к базе данных, сохранять{*экономить*} базу данных, и затем восстанавливать отправленные{*ускоренные*} символы. Эти шаги должны быть написаны в одиночный блок кода, предотвращать попытки восстановить рисунок главного компьютера, выполнять любые команды таблицы перекрестных ссылок, или обеспечивать подсказки пользователя, в то время как база данных таблицы перекрестных ссылок находится в ее восстановленном условии{*состоянии*}.
    Функции
  • AcDbDatabase:: xrefBlockId ()

  • AcDbDatabase::restoreOriginalXrefSymbols()

  • AcDbDatabase::restoreForwardingXrefSymbols()


  • Восстановление состояния

    Если Вы определили kFalse для автоотмены, applyPartialUndo объекта () функция называется, когда команда UNDO вызвана. ApplyPartialUndo () функция - виртуальная функция на AcDbObject.
    Полученные классы могут осуществлять эту функцию, чтобы интерпретировать класс - определенную информацию, сохраненную регистратором отмены и читать это в. ApplyPartialUndo () функция должна гарантировать, что ваш класс выполнил модификацию. Если не, это супер-сообщение, как показано в следующем примере.
    Если Вы осуществляете частичный механизм отмены, убедитесь, что вызвали{*назвали*} следующую функцию так, чтобы никакая регистрация не случилась по умолчанию.
    AssertWriteEnabled (kFalse, kFalse);
    Как пример, имеется AsdkPoly-функция  applyPartialUndo()
    Acad::ErrorStatus
    AsdkPoly::applyPartialUndo(AcDbDwgFiler* filer,
    AcRxClass* classObj)
    {
    // The first thing to check is whether the class matches
    // ours. If it doesn’t, we call the base class’s
    // applyPartialUndo(); hopefully, one of them will
    // take care of it.
    //
    if (classObj != AsdkPoly::desc())
    return AcDbCurve::applyPartialUndo(filer, classObj);
    // Read the op-code and call the appropriate "set"
    // method to undo what was done. The "set" does the
    // filing again for redo.
    //
    Adesk::Int16 shortCode;
    filer->readItem(&shortCode);
    PolyOpCodeForPartialUndo code;
    code = (PolyOpCodeForPartialUndo)shortCode;
    Adesk::UInt32 value32;
    switch (code) {
    case kSetNumSides:
    filer->readItem(&value32);
    AOK(setNumSides(value32));
    break;
    default:
    assert(Adesk::kFalse);
    break;
    }
    return Acad::eOk;
    }

    Возвращаемые значения против результатов функций

    Несколько ObjectARX глобальные функции имеют пустой тип возвращения, и некоторые непосредственно возвращают их результатов, но больше всего имеют int, напечатают и возвращают целочисленный код состояния, который указывает, потерпел ли функциональный запрос, за которым следуют или неудачу.
    Код RTNORM указывает, что функция преуспела; другие коды указывают неудачу или специальные условия. Библиотечные функции, которые возвращают код состояния, передают их фактических результатов (если любой) поддерживает к вызывающей программе через параметр, который пропускает ссылка.
    ПРИМЕЧАНИЕ Не путает параметры результата библиотечной функции и значения с его возвращаемым значением. Функция возвращает целочисленный код состояния. Это размещает его результатов в параметры, прошел (ссылкой) назад к функции, которая вызывает это.
    Рассмотрите следующие смоделированные объявления для нескольких типичных функций ObjectARX:
    int acdbEntNext(ads_name ent, ads_name result);
    int acedOsnap(ads_point pt, char *mode, ads_point result);
    int acedGetInt(char *prompt, int *result);
    Приложение могло вызывать эти функции со следующими инструкциями C++:
    stat = acdbEntNext(ent, entres);
    stat = acedOsnap(pt, mode, ptres);
    stat = acedGetInt(prompt, &intres);
    После того, как каждая функция вызвана, значение stat переменной указывает или успех (stat == RTNORM) или неудачу (stat == RTERROR или другой код ошибки, типа RTCAN для отмены). Последний параметр в каждом списке - параметр результата, который нужно пропустить ссылкой. Если успешно, acdbEntNext() возвращает имя примитива в его entres параметре, acedOsnap() возвращает точку в ptres, и acedGetInt() возвращается,  целое число приводит к intres. (Типы ads_name и ads_point - типы массива, который является, почему entres и ptres параметры явно не появляются как указатели.)
    ОБРАТИТЕ ВНИМАНИЕ В ObjectARX глобальных функциональных объявлениях параметры результата всегда следуют за параметрами, которые передают входные значения к функции.

    Возвращение Значений к Функциям AutoLISP

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


    Имя функции

     Результат

    AcedRetInt

     Целочисленное значение

    AcedRetReal

     Реальное значение

    AcedRetPoint

     Трехмерная точка

    AcedRetStr

     Строка

    AcedRetVal

     Значение пропускало “generically” в буфере результатов

    AcedRetName

     Примитив (RTENAME) или выбор устанавливает имя (RTPICKS) (см. главу 3 для подробной информации относительно наборов выбора и примитивов)

    AcedRetT

     AutoLISP оценивает t (истину)

    AcedRetNil

     AutoLISP оценивает ноль

    AcedRetVoid

     Пустое значение: AutoCAD не отображает результат

    AcedRetList

     Список буферов результатов, возвращенных AutoLISP

    Следующий пример показывает схему вызванной функции, когда приложение получает запрос kInvkSubrMsg. Это возвращает реальное значение AutoLISP.
    Int dofun
    ()
    {
    Ads_real x
    // Проверить{*отметить*} параметры, и ввести условия здесь.
    // Вычислить значение x.
    AcedRetReal (x);
    return GOOD;
    }
    ОБРАТИТЕ ВНИМАНИЕ, что внешняя функция может делать больше чем один запрос к функциям возвращения значения по единственному запросу kInvkSubrMsg, но функция AutoLISP возвращает только значение последней вызванной функцией.

    Всегда имейте текущую базу данных

    Хотя ObjectDBX позволяет Вам создавать много образцов AcDbDatabase, только можно быть текущая база данных. AcDb поддерживает внутренний глобальный указатель на эту текущую базу данных, и AcDbHostApplicationServices метод workingDatabase () возвращает копию этого внутреннего указателя. Всякий раз, когда AcDbDatabase:: readDwgFile () метод используется, внутренний текущий указатель базы данных сброшен, чтобы указать на ту базу данных. Когда база данных, которая является текущей,  удалена, внутренний текущий указатель базы данных установлен в NULL.
    Это означает, что в ситуациях, где ваш код читает, множественные базы данных и возможно удаляют некоторых из них по пути, Вы должны убедиться, что Вы используете AcDbHostApplicationServices::setWorkingDatabase() метод в соответствующих местах, чтобы установить внутренний текущий указатель базы данных на надлежащую текущую базу данных.
    Например, следующий код читает в одной базе данных, указанной pDbFirst (вызовите эту базу данных “сначала”). Это заставляет внутренний текущий указатель базы данных быть установленным в базу данных “ сначала. ” Код тогда читает в другой базе данных, указанной pDbSecond (вызовите эту базу данных “вторая”), который теперь заставляет внутренний текущий указатель базы данных быть установленным в базу данных “вторая”. Код затем вставляет базу данных “вторая” в базу данных “сначала” и удаляет базу данных “вторая”. Когда база данных “секунда” удалена, внутренний текущий указатель базы данных указывает на это, так что внутренний указатель установлен в NULL. Это означает, что после того, как стирание базы данных, AcDb имеет указатель текущего рисунка NULL. Это ведет к фатальным ошибкам, если любой код, к которому к ссылкам внутренний текущий указатель базы данных обращаются.
    Чтобы предотвращать это, после стирания базы данных “вторая” в коде вашего приложения, код должен назвать ведущей setWorkingDatabase() методом, проходящим в указателе на базу данных “сначала”, чтобы восстановить базу данных “сначала” как текущая база данных для ObjectDBX, следующим образом:

    // Делать "сначала" текущую базу данных.

    AcDbDatabase *pDbFirst = new AcDbDatabase(Adesk::kFalse);

    pDbFirst->readDwgFile("first.dwg");

    // Теперь заставите "секунду" быть текущая база данных.

    AcDbDatabase *pDbSecond = new AcDbDatabase(Adesk::kFalse);

    pDbSecond->readDwgFile("second.dwg");

     // Вставить "секунду" в "первый" как ABLOCK.

    Acad::ErrorStatus es;

    AcDbObjectId blockId;

    es = pDbFirst->insert(blockId, "ABLOCK", pDbSecond);

    // Удаление "секунды" делает текущую базу данных NULL.

    delete

    pDbSecond;

    // Делать текущую базу данных "сначала" снова.

     myHostServices->setWorkingDatabase(pDbFirst);

    Удалите все AcDbDatabases

    при выходе из  приложения


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

    Всегда Инициализируйте AcDbDatabase

    Вы должны всегда инициализировать по крайней мере один объект AcDbDatabase перед использованием любого кода AcDb. Это - то, потому что создание полного AcDbDatabase инициализирует набор глобальных переменных, которых некоторые библиотечные элементы требуют. (См. setWorkingDatabase () метод AcDbHostApplicationServices класса в ObjectARX Ссылке для подробностей.) Когда AutoCAD присутствует, имеется всегда “текущий рисунок” AcDbDatabase, что ObjectARX
    полагается, чтобы удовлетворить все эти требования. Приложение ObjectDBX должно подражать этому поведению.
    Если Вы намереваетесь записать непосредственно к вашей базе данных, Вы должны инициализировать это, используя конструктор AcDbDatabase с Adesk:: kTrue параметр. Эта версия конструктора создает жизнеспособный пустой рисунок, готовый к модификации и формирует таблицы базы данных и инициализирует их к значениям по умолчанию. Следующее - пример инициализирования базы данных:
    AcDbDatabase *pDb = new AcDbDatabase(Adesk::kTrue);
    Если Вы намереваетесь читать чертежный файл в базу данных, используйте конструктор AcDbDatabase с Adesk:: kFalse параметр, немедленно сопровождаемый запросом к readDwgFile () функция. Эта версия конструктора создает полностью пустую базу данных, которая полагается на последующий запрос к readDwgFile () чтобы заполнить его внутренние структуры данных. При использовании они в комбинации улучшают эффективность при чтении DWG файла по использованию другой формы конструктора, потому что таблицы и глобальные переменные должны только быть инициализированными однажды readDwgFile (). Имеется пример чтения рисунка в предварительно инициализированную базу данных:
    AcDbDatabase *pDb = new AcDbDatabase(Adesk::kFalse);
    pDb->readDwgFile(filename);
    Множитель вызывает к readDwgFile () на той же самой базе данных, не поддержаны.
    И в ObjectARX и ObjectDBX, вызывая readDwgFile () после использования Adesk:: kTrue форма конструктора некоторый, чтобы вызвать отказ{*неудачу*}, если версия DWG
    файла, который Вы читаете - Выпуск 12 или ранее. Это из-за несогласованности в пути, которым рисунки загружены до Выпуска AutoCAD 13.
    Поскольку Вы не можете предсказывать, которые рисунки ваши конечные пользователи откроются, не закодируйте следующее:
    // Не Делать этого.
    AcDbDatabase *pDb = new AcDbDatabase(Adesk::kTrue);
    pDb->readDwgFile(filename);

    Вставка Базы данных

    AcDbDatabase:: вставка () функции копируют одну базу данных в базу данных, на которую функция элемента вызвана. AutoCAD объединяет объекты, которые это определяет, типа MLINE стиля и словарей ГРУПП; однако, это не заботится о копировании определенных приложением объектов, чей монопольное использование внедрено в названном объектном словаре. Вы должны передать{*переместить*} данные прикладной программы от исходной базы данных до целевой базы данных, используя AcEditorReactor функции уведомления.
    ОБРАТИТЕ ВНИМАНИЕ На INSERT() функции исполняют глубоко имитацию, как описано в главе 18, при Глубоко Имитации. ”
    Если конфликты возникают, когда исходные и целевые базы данных объединяются (например, если обе базы данных имеют то же самое название{*имя*} linetype), AutoCAD использует версию в целевой базе данных.
    Следующая функция эквивалентна стандарту, тянущему{*рисующему*} команду INSERT:
    Acad:: ErrorStatus
     AcDbDatabase::insert(AcDbObjectId& BlockId,
    const char* pBlockName,
    AcDbDatabase* pDb);
    Эта функция копирует объекты с образцового пространства{*пробела*} входной базы данных (pDb) в
    указанный блочный отчет{*запись*} таблицы (pBlockName) и
    возвращает блок ID нового блочного отчета{*записи*} таблицы (blockId). Приложение должно тогда создать ссылку{*справочники*} к блочной таблице, делают запись и прибавляют это к базе данных.
    Следующая функция эквивалентна команде AutoCAD:
    Acad:: ErrorStatus
    AcDbDatabase::insert (const AcGeMatrix3d& Xform,
    AcDbDatabase* pDb);
    Эта функция копирует объекты с образцового пространства{*пробела*} входной базы данных (pDb) и помещает их в текущее пространство{*пробел*} новой базы данных (бумажное пространственное или образцовое пространство{*пробел*}), применяя указанное преобразование (xform) к объектам. 

    Вставлять блок с атрибутами в рисунок

    1 Создают примитив блок-ссылки (AcDbBlockReference).
    2 Называют setBlockTableRecord () функцией, чтобы определить объект ID упомянутой записи таблицы блоков. (Объект ID может также быть определен непосредственно в конструкторе блок-ссылки.)
    3 Добавляют в конец блок-ссылку к записи таблицы блоков (пространство модели, пространство листа, или некоторый другой блок).
    4 Используют запись таблицы блоков iterator на упомянутой записи таблицы блоков, ища определения атрибута. Для каждого найденного, создайте новый AcDbAttribute примитив, заполните это с данными определения атрибута, и затем добавьте в конец это к блок-ссылке, используя appendAttribute () функция.
    Следующий пример создает блок-ссылку, заполняет атрибуты, и добавляет ссылку к базе данных. Это использует глобальные функции, чтобы получить ввод пользователя. CreateBlockWithAttributes () функция, показанная в предыдущем разделе используется, чтобы создать блок-ссылку. Этот пример использует запись таблицы блоков iterator, чтобы шагнуть через определения атрибута и создавать соответствующий атрибут для каждого определения атрибута. Атрибуты со значением установлены от первоначального определения атрибута, используя setPropertiesFrom () функция.
    void
    addBlockWithAttributes()
    {
    // Get an insertion point for the block reference,
    // definition, and attribute definition.
    //
    AcGePoint3d basePoint;
    if (acedGetPoint(NULL, "\nEnter insertion point: ",
    asDblArray(basePoint)) != RTNORM)
    return;
    // Get the rotation angle for the attribute definition.
    //
    double textAngle;
    if (acedGetAngle(asDblArray(basePoint),
    "\nEnter rotation angle: ", &textAngle) != RTNORM)
    return;
    // Define the height used for the attribute definition text.
    //
    double textHeight;
    if (acedGetDist(asDblArray(basePoint),
    "\nEnter text height: ", &textHeight) != RTNORM)
    return;
    // Build the block definition to be inserted.
    //
    AcDbObjectId blockId;
    defineBlockWithAttributes(blockId, basePoint,

    textHeight, textAngle);

    // Step 1: Allocate a block reference object.

    //

    AcDbBlockReference *pBlkRef = new AcDbBlockReference;

    // Step 2: Set up the block reference to the newly

    // created block definition.

    //

    pBlkRef->setBlockTableRecord(blockId);

    // Give it the current UCS normal.

    //

    struct resbuf to, from;

    from.restype = RTSHORT;

    from.resval.rint = 1; // UCS

    to.restype = RTSHORT;

    to.resval.rint = 0; // WCS

    AcGeVector3d normal(0.0, 0.0, 1.0);

    acedTrans(&(normal.x), &from, &to, Adesk::kTrue,

    &(normal.x));

    // Set the insertion point for the block reference.

    //

    pBlkRef->setPosition(basePoint);

    // Indicate the LCS 0.0 angle, not necessarily the UCS 0.0 angle.

    //

    pBlkRef->setRotation(0.0);

    pBlkRef->setNormal(normal);

    // Step 3: Open the current database’s model space

    // block Table Record.

    //

    AcDbBlockTable *pBlockTable;

    acdbHostApplicationServices()->workingDatabase()

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

    AcDbBlockTableRecord *pBlockTableRecord;

    pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord,

    AcDb::kForWrite);

    pBlockTable->close();

    // Append the block reference to the model space

    // block Table Record.

    //

    AcDbObjectId newEntId;

    pBlockTableRecord->appendAcDbEntity(newEntId, pBlkRef);

    pBlockTableRecord->close();

    // Step 4: Open the block definition for read.

    //

    AcDbBlockTableRecord *pBlockDef;

    acdbOpenObject(pBlockDef, blockId, AcDb::kForRead);

    // Set up a block table record iterator to iterate

    // over the attribute definitions.

    //

    AcDbBlockTableRecordIterator *pIterator;

    pBlockDef->newIterator(pIterator);

    AcDbEntity *pEnt;

    AcDbAttributeDefinition *pAttdef;

    for (pIterator->start(); !pIterator->done(); pIterator->step())

    {

    // Get the next entity.

    //

    pIterator->getEntity(pEnt, AcDb::kForRead);

    // Make sure the entity is an attribute definition

    // and not a constant.

    //

    pAttdef = AcDbAttributeDefinition::cast(pEnt);

    if (pAttdef != NULL && !pAttdef->isConstant()) {


    // We have a non-constant attribute definition,

    // so build an attribute entity.

    //

    AcDbAttribute *pAtt = new AcDbAttribute();

    pAtt->setPropertiesFrom(pAttdef);

    pAtt->setInvisible(pAttdef->isInvisible());

    // Translate the attribute by block reference.

    // To be really correct, the entire block

    // reference transform should be applied here.

    //

    basePoint = pAttdef->position();

    basePoint += pBlkRef->position().asVector();

    pAtt->setPosition(basePoint);

    pAtt->setHeight(pAttdef->height());

    pAtt->setRotation(pAttdef->rotation());

    pAtt->setTag("Tag");

    pAtt->setFieldLength(25);

    char *pStr = pAttdef->tag();

    pAtt->setTag(pStr);

    free(pStr);

    pAtt->setFieldLength(pAttdef->fieldLength());

    // The database column value should be displayed.

    // INSERT prompts for this.

    //

    pAtt->setTextString("Assigned Attribute Value");

    AcDbObjectId attId;

    pBlkRef->appendAttribute(attId, pAtt);

    pAtt->close();

    }

    pEnt->close(); // use pEnt... pAttdef might be NULL

    }

    delete pIterator;

    pBlockDef->close();

    pBlkRef->close();

    }

    Встроенная MFC Поддержка Интерфейса пользователя

    ObjectARX
    имеет набор MFC Интерфейса пользователя (UI) связанные классы, которые легко позволяют Вам обеспечивать непротиворечивый UI. Это означает, что ваш UI может вести себя и иметь появление{*вид*} AutoCAD UI. Строго рекомендует использовать эти классы, так как они позволяют вашему приложению быть более сильно интегрированными с AutoCAD UI. Autodesk MFC система разделен на две библиотеки. Первый вызван{*назван*} AdUi и не Определенный автохамом. Второй вызван{*назван*} AcUi и содержит Определенное автохамом появление{*вид*} и поведение.
    AdUi - MFC
    динамически компонуемая библиотека расширения{*продления*}, имел обыкновение расширять{*продлевать*} некоторых из UI-имеющихся отношение классов MFC. Библиотека была разработана для использования с AutoCAD и другими изделиями{*программами*} Autodesk и содержит основные функциональные возможности. Библиотека компаньонов, AcUi, формирует на AdUi
    структуру и обеспечивает AutoCAD- определенное появление{*вид*} и поведение. AdUi и AcUi библиотеки обеспечивают классы, которые расширяют{*продлевают*} обеспеченный MFC способами, которые позволяют ARX
    разработчикам использовать те же самые UI функциональные возможности, найденные в AutoCAD. MFC разработчики может без швов использовать эти классы. Перечислены ниже основные области добавленных функциональных возможностей, обеспеченных AdUi и AcUi.
    Чтобы использовать AdUi в приложении MFC-based, исходные файлы C++ проекта должны включить adui.h, и проект должен связать adui15.lib (adui15.dll
    библиотека импорта).
    Чтобы использовать AcUi в MFC-ОСНОВАННОМ приложении AutoCAD, исходные файлы C++ проекта должны включить adui.h, тогда acui.h, и проект должен связать acui15.lib
    и adui15.lib. AutoCAD вызывает подпрограмму инициализации библиотеки, InitAcUiDLL (), который также обрабатывает AdUi инициализацию (через InitAdUiDLL () запрос); поэтому ваша прикладная потребность не повторно инициализирует AcUi или AdUi.
    ПРЕДУПРЕЖДЕНИЕ! Хотя adui15.dll может быть вызван от приложений MFC-based других чем AutoCAD (или другие программы Autodesk), предназначенное использование библиотеки - Autodesk и третьими лицами явно для создания программного обеспечения, чтобы работать исключительно с AutoCAD, или другими изделиями Autodesk. Использование этого DLL для не- AutoCADа, автономные программы не разрешаются согласно лицензионному соглашению AutoCAD.

    AdUi и AcUi

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

    § изменение размеров Диалога

    § постоянство данных Диалога

    § Табулированные диалоги

    § Расширяемые табулированные диалоги

    § Контекстно-зависимая справка и справка F1

    § взаимодействие Диалога с редактором рисунка AutoCAD

    § кнопки Bitmap, которые являются удобными

    § Статические растровые кнопки

    § кнопки Bitmap, которые являются, перетащат и опустить узлы

    § кнопки точечного рисунка Стиля инструментальной панели

    § кнопки Owner-draw, которые являются удобными

    § Диалог и управление поддерживают для стандарта ToolTips

    § Диалог и управление поддерживают для TextTips (которые отображают обрезанный текст)

    § Диалог и поддержка управления для DrawTips (владелец - тянут TextTips)

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

    § Поля со списком, которые отображают и позволяют выбор многого AutoCAD определенные элементы

    § Состыковывающиеся окна строки управления для использования с AutoCAD

    § Определенные в AutoCAD растровые кнопки (кнопки Pick и Select)

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

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

    Введение Файла Проекта ATL

    Обертки COM могут быть созданы как отдельный DLLS, или объединен с вашим ObjectARX-приложением. Оба метода используют ATL Microsoft AppWizard, чтобы упростить процесс. Отдельный DLL позволяет системе управлять ресурсами более эффективно; это может выпускать объекты COM, когда они не необходимы, даже если ObjectARX-приложение не может быть разгружено.
    Основывать проект для обертки COM в отдельном DLL
    1.
    Удостоверятся axauto15.dll, который должен быть в том же самом каталоге как acad.exe, находится в вашем пути поиска файлов.
    2. От меню Microsoft visual c ++ File, выберите Новый.
    3. COM ATL Выбора AppWizard на позиции табуляции Projects и вводит проектное имя.
    4. Выбирают тип сервера DLL. Дополнительные проектные назначения необязательные.
    5. Выбирают Finish и OK.
    6. От меню Insert или подручного меню представления Класса, выберите Новый Объект ATL.
    7. Выбирают Простой Объект в категории Объектов и выбирают Затем.
    8. Вводят C++ Короткое Имя на позиции табуляции Names; Мастер снабдит значения по умолчанию для остающихся имен.
    9. На позиции табуляции Attributes, выберите Поддержку IErrorInfo.
    10. Выбирают ХОРОШО.
    11. От меню Project, выберите Назначения.
    12. На C / C ++ позиция табуляции, выберите Язык C++ из раскрывающегося списка Категории, и выбор Позволяет обработку особых ситуаций.
    13. На позиции табуляции Link, добавьте axauto15.lib, oleaprot.lib, и любые другие упомянутые ObjectARX библиотеки.
  • Выбирают OK.

  • Основывать проект, который объединяет обертку COM с существующим ObjectARX-приложением
    1. Удостоверятся axauto15.dll, который должен быть в том же самом каталоге как acad.exe, находится в вашем пути поиска файлов.

    2. От меню Microsoft visual c ++ File, выберите Новый.
    3. COM ATL Выбора AppWizard на позиции табуляции Projects и вводит проектное{*строительное*} имя.
    4. Выбирают тип сервера DLL. Дополнительные проектные{*строительные*} назначения необязательные.
    5. Выбирают Конец и OK.
    6. Добавляют весь CPP и H файлы от вашего ObjectARX-приложения.
    7. Модифицируют ваши включаемые и библиотечные пути и DLL точку входа как соответствующий ObjectARX-приложению.
    8. Модифицируют файл DEF,  добавляя точки входа. Измените имя DLL, чтобы иметь ARX расширение.
    9. В этой точке Вы должны быть способны компилировать, чтобы удостовериться, что ObjectARX-приложение формирует успешно.
    10. От меню Insert или подручного меню представления Класса, выберите Новый Объект ATL.
    11. Выбирают Простой Объект в категории Объектов и выбирают Затем.
    12. Вводят C++ Короткое Имя на позиции табуляции Names; Мастер снабдит значения по умолчанию для остающихся имен.
    13. На позиции табуляции Attributes, выберите Поддержку IErrorInfo.
    14. Выбирают OK.
    15. От меню Project, выберите Назначения.
    16. На C / C ++ позиция табуляции, выберите Язык C++ из раскрывающегося списка Категории, и выбор Позволяет обработку особых ситуаций.
    17. На позиции табуляции Link, добавьте axauto15.lib, oleaprot.lib, и любые другие упомянутые ObjectARX библиотеки.
    18. Выбирают OK.

    Введение Списков и Всплывающих Списков

    Вы основываете списки, отображенные в списках, и во всплывающих списках,  используя последовательность вызывает к трем функциям: ads_start_list (), ads_add_list (), и ads_end_list (). Как только список был создан, Вы можете исправлять это. Имеются три возможных операции, которые определены ads_start_list () параметр операции функции (чей значения показываются в круглых скобках в следующем списке).
    §
    Создают новый список (LIST_NEW).
    После ads_start_list () запрос, Вы можете вызывать ads_add_list () неоднократно.
    Каждый ads_add_list () запрос прибавляет новый элемент к списку. Конечная обработка списка,  вызывая ads_end_list ().
    § Изменяют элемент в списке (LIST_CHANGE).
    После ads_start_list (), вызовите ads_add_list () однажды заменить элемент, чей индекс был определен в ads_start_list () запрос. ( Если Вы называете ads_add_list () больше чем однажды, это заменяет тот же самый элемент снова.) В конце обработки  вызывают ads_end_list ().
    § Добавляют элемент к списку (LIST_APPEND).
    После ads_start_list (), вызовите ads_add_list () чтобы добавить элемент к концу списка. Если Вы продолжаете вызывать ads_add_list (), большее количество элементов добавлено в конец, пока Вы не вызываете ads_end_list ().
    Независимо от которой списка операции Вы делаете, Вы должны вызвать три функции в правильной последовательности: ads_start_list(), тогда ads_add_list() (возможно больше чем однажды) и ads_end_list().
    Списки наиболее легко представлены связанными буферами результатов, как показано в следующем примере:
    struct resbuf *appnames, *rb;
    // Initialize the appnames list here.
    //
    ...
    rb = appnames;
    ads_start_list(hdlg, "selections", LIST_NEW, 0);
    while (rb != NULL) {
    ads_add_list(rb->resval.rstring);
    rb = rb->rbnext;
    }
    ads_end_list();
    Для коротких списков, проще передать индивидуальные строки. Список буфера результата не требован.
    Значение list_box поля ввода - индекс (или индексы) отобранного элемента (или элементы). Если ваша программа должна знать фактический текст, связанный с индексом, это должно сохранить первоначальный список. Это должно также проследить изменения, сделанные методами, показанными в следующих примерах.

    Элементы списка Добавления в конец подобны созданию нового списка. Например, appnames имеет 12 элементов в этом, и Вы хотите добавить другой список, вызвал newnames:
    (start_list "selections" 2)
    (mapcar ’add_list newnames)
    (end_list)
    В ObjectARX, Вы должны определить индексное значение, но ads_add_list () игнорирует это в добавляющейся операции.
    struct resbuf *appnames, *newnames, *rb;
    rb = newnames;
    ads_start_list(hdlg, "selections", LIST_APPEND, 0);
    while (rb != NULL) {
    ads_add_list(rb->resval.rstring);
    rb = rb->rbnext;
    }
    ads_end_list();
    Изменение единственного элемента требует только одного ads_add_list () запрос. В следующем примере, Вы определяете индекс элемента, чтобы измениться:
    ads_start_list(hdlg, "selections", LIST_CHANGE, 5);
    ads_add_list("SURPRISE!");
    ads_end_list();
    Вы не можете удалять элемент списка или вставлять элемент без того, чтобы восстановить полный список.

    Приложения ObjectArx могут быть созданы,

    Приложения ObjectArx могут быть созданы, чтобы воспользоваться преимуществом Microsoft
    Фундаментальный класс (MFC) библиотека. Эта глава обсуждает, как формировать ваш
    Приложения ObjectArx, чтобы использовать MFC и как встроенный AutoCAD
    MFC
    система может использоваться, чтобы создать диалоги, которые ведут себя и работают
    AutoCAD.


    ObjectDBX SDK - интерфейс среди ведущих приложений, рисуя (.dwg) файлы, заказное приложение (.arx) файлы, и заказной объект (.dbx) файлы.

    Ввод Кнопки Изображения

    Вы можете обрабатывать кнопку изображения просто как кнопка — то есть вызывать отдельное действие. Однако, PDB средство также дает Вам опцию определения областей кнопки так, чтобы принятое действие зависело, на которой части кнопки изображения пользователь выбирает. Механизм для этого прямой: действие кнопки изображения или повторный вызов возвращают (X, Y) местоположение, которое пользователь выбрал. Координаты - в пределах диапазона специфического поля ввода кнопки изображения (как возвращено функциями измерения). Ваше приложение должно назначить значение к местоположениям на поле ввода кнопки изображения,  неявно определяя области изображения.
    В следующем примере, кнопка изображения имеет два цветных образчика, созданные ads_fill_image (). Вы можете выбирать один или другой, в зависимости от которой области пользователь выбирает. Если кнопка изображения разделена горизонтально (темный выше, индикатор ниже), повторный вызов должен проверить только одно измерение. Не используйте структуру точки типа ads_point, чтобы сохранить координаты pickpoint, потому что их пропускают как длинные целые числа:
    char result[31]; // Global char array
    static void CALLB
    pick_shade(ads_callback_packet cbpkt)
    {
    long threshold, pick_y = cbpkt->y;
    ads_hdlg hdlg = cbpkt->dialog;
    short x, y;
    ads_dimensions_tile(hdlg, "image_sel", &x, &y);
    threshold = y/2;
    // Remember the origin at upper left.
    //
    if (pick_y > threshold)
    strcpy(result, "Light");
    else
    strcpy(result, "Dark");
    }

    Выполнение COM AutoCAD

    OPM - по существу контроль, который анализирует информацию типа от объектов COM, чтобы определить их свойства. Когда объекты в рисунке отобраны, набор выборов преобразован в массив указателей IUnknown, представляющих объекты COM, которые переносят по словам все родные примитивы в AutoCAD. Эти обертки объекта COM - фундаментальная поддержка для ActiveX Автоматизации, связывают с помощью интерфейса и - основные объекты, с которыми OPM связывается.
    Эти обертки объекта COM осуществляют IDISPATCH также как другие интерфейсы.
    IDispatch - COM, связывают с помощью интерфейса использования OPM, чтобы получить и установить данные свойства. Это - также родное объектное представление в VB и VBA. Чтобы определять, который, свойства являются доступными для объекта, OPM, вызывают IDISPATCH:: GetTypeInfo (), который все обертки COM AutoCAD осуществляют.
    Эта функция возвращает информацию типа для объекта (объект, который осуществляет ITYPEINFO). ITypeInfo - стандарт интерфейс Microsoft, который переносит по словам структуру данных, описывающую методы и свойства, доступные на том объекте. Коллекции информации типа, используемой VB и VBA, чтобы определить модель объекта ActiveX названы библиотеки типа.
    OPM берет информацию свойства, и основанный на типе свойства, поскольку это определено в IDL, создает редактора свойства окно, соответствующее тому типу свойства. Например, если тип свойства числовой или текстовый, это создает окно редактирования. Если это - перечисление, это создает поле со списком с перечисленным списком значения. Если это - готовое свойство типа Цвета, Уровня, Типа линии, Lineweight, или других встроенных свойств, это создает стандарт drop-downs для тех, которые являются, тот же самый что касается Инструментальной панели Свойства объекта (OPT).
    Статическая информация типа для каждого объекта COM - не единственный источник информации свойства для OPM. OPM также делает запрос объекта для нескольких других интерфейсов, чтобы управлять вещи типа классификации свойства, названия значения свойства для раскрывающихся списков, и инициализация диалогов для редактирования " в собственность " (типа диалогов кнопки замещающего знака). Они будут описаны подробно позже в этой секции, но будут упомянуты все вместе как “ flavoring ” интерфейсы.

    Выполнение итераций через Вершину в Ломаной линии

    Следующее выполнение итераций показов примера через вершину в ломаной линии, использующей вершину iterator. Это тогда печатает координаты для каждой вершины.
    // Принимает объект ID AcDb2dPolyline, открывает это, и получает вершину iterator.
    // Это тогда выполняет итерации через вершину, распечатывая местоположение вершины.
    void
    iterate(AcDbObjectId plineId)
    {
    AcDb2dPolyline *pPline;
    acdbOpenObject(pPline, plineId, AcDb::kForRead);
    AcDbObjectIterator *pVertIter= pPline->vertexIterator();
    pPline->close(); // Finished with the pline header.
    AcDb2dVertex *pVertex;
    AcGePoint3d location;
    AcDbObjectId vertexObjId;
    for (int vertexNumber = 0; !pVertIter->done();
    vertexNumber++, pVertIter->step())
    {
    vertexObjId = pVertIter->objectId();
    acdbOpenObject(pVertex, vertexObjId,
    AcDb::kForRead);
    location = pVertex->position();
    pVertex->close();
    acutPrintf("\nVertex #%d’s location is"
    " : %0.3f, %0.3f, %0.3f", vertexNumber,
    location[X], location[Y], location[Z]);
    }
    delete pVertIter;
    }

    Выполнение итераций через Запись таблицы блоков

    Следующий пример демонстрирует, как выполнить итерации через элементы в записи таблицы блоков и распечатывать элементы.
    PrintAll () функция открывает таблицу блоков для чтения, и затем это открывает имя блока, снабженное пользователем. Новый iterator шагает через записи таблицы блоков. Если запись содержит примитив, iterator печатает сообщение относительно примитива.
    void
    printAll()
    {
    int rc;
    char blkName[50];
    rc = acedGetString(Adesk::kTrue,
    "Enter Block Name : ",
    blkName);
    if (rc != RTNORM)
    return;
    if (blkName[0] == ’\0’) {
    if (acdbHostApplicationServices()->workingDatabase()
    ->tilemode() == Adesk::kFalse) {
    struct resbuf rb;
    acedGetVar("cvport", &rb);
    if (rb.resval.rint == 1) {
    strcpy(blkName, ACDB_PAPER_SPACE);
    } else {
    strcpy(blkName, ACDB_MODEL_SPACE);
    }
    } else {
    strcpy(blkName, ACDB_MODEL_SPACE);
    }
    }
    AcDbBlockTable *pBlockTable;
    acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pBlockTable, AcDb::kForRead);
    AcDbBlockTableRecord *pBlockTableRecord;
    pBlockTable->getAt(blkName, pBlockTableRecord,
    AcDb::kForRead);
    pBlockTable->close();
    AcDbBlockTableRecordIterator *pBlockIterator;
    pBlockTableRecord->newIterator(pBlockIterator);
    for (; !pBlockIterator->done(); pBlockIterator->step())
    {
    AcDbEntity *pEntity;
    pBlockIterator->getEntity(pEntity, AcDb::kForRead);
    AcDbHandle objHandle;
    pEntity->getAcDbHandle(objHandle);
    char handleStr[20];
    objHandle.getIntoAsciiBuffer(handleStr);
    const char *pCname = pEntity->isA()->name();
    acutPrintf("Object Id %lx, handle %s, class %s.\n",
    pEntity->objectId(), handleStr, pCname);
    pEntity->close();
    }
    delete pBlockIterator;
    pBlockTableRecord->close();
    acutPrintf("\n");
    }

    Выполнение итераций по Таблицам

    Код в следующем примере создает iterator, который идет через записи таблицы идентификаторов в linetype таблице. Это получает каждую запись, открывает это для чтения, получает имя linetype, закрывает запись, и затем печатает имя linetype. В конец, программа удаляет iterator.
    void
    iterateLinetypes()
    {
    AcDbLinetypeTable *pLinetypeTbl;
    acdbHostApplicationServices()->workingDatabase()
    ->getSymbolTable(pLinetypeTbl, AcDb::kForRead);
    // Create a new iterator that starts at table
    // beginning and skips deleted.
    //
    AcDbLinetypeTableIterator *pLtIterator;
    pLinetypeTbl->newIterator(pLtIterator);
    // Walk the table, getting every table record and
    // printing the linetype name.
    //
    AcDbLinetypeTableRecord *pLtTableRcd;
    char *pLtName;
    for (; !pLtIterator->done(); pLtIterator->step()) {
    pLtIterator->getRecord(pLtTableRcd, AcDb::kForRead);
    pLtTableRcd->getName(pLtName);
    pLtTableRcd->close();
    acutPrintf("\nLinetype name is: %s", pLtName);
    free(pLtName);
    }
    delete pLtIterator;
    pLinetypeTbl->close();
    }

    Выполнение итераций по Входам Словаря

    Iterator класс для словарей - AcDbDictionaryIterator. Следующая выборка кода получает словарь (ASDK_DICT) от названного объектного словаря.
    Это тогда использует словарь iterator, чтобы шагнуть через входы словаря и печатать значение сохраненного целого числа. Наконец, это удаляет iterator и закрывает словарь.
    void
    iterateDictionary()
    {
    AcDbDictionary *pNamedobj;
    acdbHostApplicationServices()->workingDatabase()
    ->getNamedObjectsDictionary(pNamedobj, AcDb::kForRead);
    // Get a pointer to the ASDK_DICT dictionary.
    //
    AcDbDictionary *pDict;
    pNamedobj->getAt("ASDK_DICT", (AcDbObject*&)pDict,
    AcDb::kForRead);
    pNamedobj->close();
    // Get an iterator for the ASDK_DICT dictionary.
    //
    AcDbDictionaryIterator* pDictIter = pDict->newIterator();
    AsdkMyClass *pMyCl;
    Adesk::Int16 val;
    for (; !pDictIter->done(); pDictIter->next()) {
    // Get the current record, open it for read, and
    // print its data.
    //
    pDictIter->getObject((AcDbObject*&)pMyCl,
    AcDb::kForRead);
    pMyCl->getData(val);
    pMyCl->close();
    acutPrintf("\nintval is: %d", val);
    }
    delete pDictIter;
    pDict->close();
    }

    Выполнение Объектов Автоматизации

    Следующие Определенные автохамом интерфейсы поддержаны объектами COM в API Автоматизации, которые представляют объект в базе данных:


    IacadBaseObject

    Поддерживает связь к AcDbObject через AcDbObjectId.

    IacadObjectEvents

    Исходный интерфейс, который уведомляет клиентов COM когда AcDbObject изменился.

    IretrieveApplication

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

    IacadObject

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

    IacadEntity

    Выставляет все общие свойства и методы, которые обращаются к каждому примитиву в базе данных. (Только применимый для AcDbEntity –наследованных классов.)

    Следующие интерфейсы - не AutoCAD, определенный, но требованы для надлежащего поведения:


    Idispatch

    Позволяет поздно обязывать. Броузеры типа OPM
    требуют этого интерфейса.

    IconnectionPointContainer

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

    IconnectionPoint

    Используемым, чтобы позволить клиентов COM, чтобы просить о уведомлении.

    IsupportErrorInfo

    Сообщает клиентам COM что объектная информация ошибки поддержек.

    Если Вы создаете класс COM, чтобы представить AcDbObject-полученный класс, Вы будете должны осуществить все эти интерфейсы.

    Выполнение Приложений ObjectArx от AutoLISP

    Приложение ObjectArx может определять набор функций, известных к AutoLISP как внешние функции, используя acedDefun (). После того, как приложение загружено, Вы можете вызывать внешнюю функцию точно, поскольку Вы можете вызывать встроенную или определяемую пользователем функцию AutoLISP. Переменные AutoLISP можно пропускать как параметры к внешней функции, и внешняя функция может возвращать результат.
    Внешняя функция может также запрашивать пользователя вводить данные, или от клавиатуры или,  определяя пункты{*точки*} или объекты{*цели*} с устройством управления позицией, и внешняя функция может устанавливать Windows или AutoCAD платформа-независимая справка.
    Внешняя функция может быть вызвана функцией AutoLISP, также как в интерактивном режиме. Приложения ObjectArx не могут вызывать функции AutoLISP. Приложение ObjectArx может отыскивать и устанавливать значение символов AutoLISP (тип данных символа должен быть распознаваемый к программе C++).
    Приложение ObjectArx может определять новую команду AutoCAD с тем же самым C:XXX соглашением как AutoLISP. Вы вызываете внешнюю функцию,  вводя ее название{*имя*} в Приглашении ко вводу команды, без круглых скобок.
    Определение внешней функции заменяет любое предыдущее определение того же самого названия{*имени*}. Если два Приложения ObjectArx определяют функции с тем же самым названием{*именем*}, функция в первом приложении, которое будет загружено потеряна; если Вы разгружаете второе приложение, Вы не можете вызывать{*называть*} двойную функцию.

    Вырождение

    Некоторые операции могут приводить к созданию выродившихся примитивов. Выродившееся означает, что, хотя заканчивающийся объект принадлежит специфическому классу, его геометрия больше не может соответствовать требованиям того класса. Например, если Вы начинаете с круговой дуги и затем устанавливаете ее угол начала, равняются ее конечному углу, Вы фактически имеете точку вместо круговой дуги. Геометрически, объект - точка, но ее тип во время выполнения - все еще круговая дуга. Вы можете использовать один из isDegenerate () функции, чтобы определить,является ли объект выродившимся. Первая версия каждой пары функций возвращает тип. Вторая версия возвращает невыродившийся объект различного типа во время выполнения. В предыдущем примере, это возвратило бы точку:
    Adesk::Boolean
    AcGeCurve2d::isDegenerate(
    AcGe::EntityId& degenerateType,
    const AcGeTol&=AcGeContext::gTol) const;
    Adesk::Boolean
    AcGeCurve2d::isDegenerate(
    AcGeEntity2d*& pConvertedEntity,
    const AcGeTol&=AcGeContext::gTol) const;
    Adesk::Boolean
    AcGeCurve3d::isDegenerate(
    AcGe::EntityId& degenerateType,
    const AcGeTol&=AcGeContext::gTol) const;
    Adesk::Boolean
    AcGeCurve3d::isDegenerate(
    AcGeEntity3d*& pConvertedEntity,
    const AcGeTol&=AcGeContext::gTol) const;

    Высвечивание Вложенных Блочных Ссылок

    Пример, который следует за показами, высвечивающими вложенные блочные ссылки{*справочники*}. Как показано в следующем числе{*рисунке*}, пример создает шесть примитивов: три polys (заказной примитив) и три поля. Это также создает три блочных ссылки{*справочников*} (вставки).
    Вставьте 3 (ins3) - вставка блока, который содержит poly3 и box3. Вставьте 2 (ins2) - вставка блока, который содержит poly2, box2, и ins3. Вставьте 1 (ins1) - вставка блока, который содержит poly1, box1, и ins2.
    После того, как вставки созданы, пример высвечивает различные компоненты.
    void
    createInsert()
    {
    // Create a nested insert and try highlighting its
    // various subcomponents.
    //
    // There are six entities in total -- three polys and
    // three boxes (solids). We’ve named them: poly1, poly2,
    // poly3, and box1, box2, box3. We also have three
    // inserts: ins1, ins2, ins3.
    //
    // ins3 is an insert of a block that contains (poly3, box3)
    // ins2 is an insert of a block that contains (poly2, box2,
    // ins3).
    // ins1 is an insert of a block that contains (poly1, box1,
    // ins2).
    //
    // Let's create these entities first.
    //
    // Polys
    //
    AsdkPoly *poly1, *poly2, *poly3;
    AcGeVector3d norm(0, 0, 1);
    if ((poly1=new AsdkPoly)==NULL){
    acutPrintf("\nOut of Memory.");
    return;
    }
    if (poly1->set(AcGePoint2d(2, 8),AcGePoint2d(4, 8), 6, norm, "POLY1",0) != Acad::eOk){
    acutPrintf("\nCannot create object with given parameters.");
    delete poly1;
    return;
    }
    if ((poly2=new AsdkPoly)==NULL){
    acutPrintf("\nOut of Memory.");
    delete poly1;
    return;
    }
    if (poly2->set(AcGePoint2d(7, 8), AcGePoint2d(9, 8), 6, norm, "POLY2",0) != Acad::eOk){
    acutPrintf("\nCannot create object with given parameters.");
    delete poly1;
    delete poly2;
    return;
    }
    if ((poly3=new AsdkPoly)==NULL){
    acutPrintf("\nOut of Memory.");
    delete poly1;
    delete poly2;
    return;
    }
    if (poly3->set(AcGePoint2d(12, 8),AcGePoint2d(14, 8), 6, norm, "POLY3",0)!=Acad::eOk){

    acutPrintf("\ nCannot create object with given parameters.");

    delete poly1;

    delete poly2;

    delete poly3;

    return;

    }

    postToDb(poly1);

    postToDb(poly2);

    postToDb(poly3);

    // Boxes

    //

    AcDb3dSolid *box1, *box2, *box3;

    box1 = new AcDb3dSolid();

    box2 = new AcDb3dSolid();

    box3 = new AcDb3dSolid();

    box1->createBox(2, 2, 2);

    box2->createBox(2, 2, 2);

    box3->createBox(2, 2, 2);

    AcGeMatrix3d mat;

    mat(0, 3) = 2; mat(1, 3) = 2;

    box1->transformBy(mat);

    mat(0, 3) = 7; mat(1, 3) = 2;

    box2->transformBy(mat);

    mat(0, 3) = 12; mat(1, 3) = 2;

    box3->transformBy(mat);

    postToDb(box1);

    postToDb(box2);

    postToDb(box3);

    // Inserts

    //

    // Arguments to BLOCK are:

    // blockname,

    // insert point,

    // select objects,

    // empty string for selection complete

    // Arguments to INSERT are:

    // blockname,

    // insertion point,

    // xscale,

    // yscale,

    // rotation angle

    //

    acedCommand_command(RTSTR, "_globcheck", RTSHORT, 0, RTNONE);

    acedCommand(RTSTR, "BLOCK", RTSTR, "blk3", RTSTR, "0,0",

    RTSTR, "14,8", RTSTR, "11,1", RTSTR, "",

    RTNONE);

    acedCommand(RTSTR, "INSERT", RTSTR, "blk3", RTSTR,

    "0,0", RTSHORT, 1, RTSHORT, 1, RTSHORT,

    0, RTNONE);

    acedCommand(RTSTR, "BLOCK", RTSTR, "blk2", RTSTR, "0,0",

    RTSTR, "9,8", RTSTR, "6,1", RTSTR, "11,1",

    RTSTR, "", RTNONE);

    acedCommand(RTSTR, "INSERT", RTSTR, "blk2", RTSTR,

    "0,0", RTSHORT, 1, RTSHORT, 1, RTSHORT,

    0, RTNONE);

    acedCommand(RTSTR, "BLOCK", RTSTR, "blk1", RTSTR, "0,0",

    RTSTR, "4,8", RTSTR, "1,1", RTSTR, "6,1",

    RTSTR, "", RTNONE);

    acedCommand(RTSTR, "INSERT", RTSTR, "blk1", RTSTR,

    "0,0", RTSHORT, 1, RTSHORT, 1, RTSHORT,

    0, RTNONE);

    return;

    }

    void

    hilitInsert()

    {

    Adesk::Boolean interrupted = Adesk::kFalse;


    acutPrintf("\nSelect an insert");

    Acad::ErrorStatus es = Acad::eOk;

    AcDbEntity *ent = NULL;

    AcDbEntity *ent2 = NULL;

    AcDbBlockReference *blRef = NULL;

    AcDbObjectId objectId, blRefId;

    ads_name ename, sset;

    for (;;) {

    switch (acedSSGet(NULL, NULL, NULL, NULL, sset)) {

    case RTNORM:

    {

    struct resbuf *rb;

    if (acedSSNameX(&rb, sset, 0) != RTNORM) {

    acutPrintf("\n acedSSNameX failed");

    acedSSFree(sset);

    return;

    }

    int sel_method;

    ads_name subname;

    short marker;

    AcGePoint3d pickpnt;

    AcGeVector3d pickvec;

    if (!extractEntityInfo(rb,

    sel_method,

    ename,

    subname,

    marker,

    pickpnt,

     pickvec)) {

    acutPrintf("\nextractEntityInfo failed");

    acedSSFree(sset);

    return;

    }

    acedSSFree(sset);

    assert(marker != 0);

    if (marker == 0) {

    acutPrintf("\nmarker == 0");

    return;

    }

    // Get the insert first.

    //

    AOK(acdbGetObjectId(blRefId, ename));

    AOK(acdbOpenAcDbEntity(ent, blRefId,

    AcDb::kForRead));

    assert(ent != NULL);

    blRef = AcDbBlockReference::cast(ent);

    if (blRef == NULL) {

    acutPrintf("\nNot an insert.");

    AOK(ent->close());

    continue;

    }

    struct resbuf *insStack;

    ads_point pickpoint;

    ads_matrix adsmat;

    pickpoint[0] = pickpnt[0];

    pickpoint[1] = pickpnt[1];

    pickpoint[2] = pickpnt[2];

    // Now get details on the entity that was

    // selected.

    //

    if (acedNEntSelP(NULL, ename, pickpoint, TRUE,

    adsmat, &insStack) != RTNORM)

    {

    acutPrintf("\nFailure in acedNEntSelP");

    return;

    }

    assert(insStack != NULL);

    AOK(acdbGetObjectId(objectId, ename));

    AOK(acdbOpenAcDbEntity(ent2, objectId,

    AcDb::kForRead));

    assert(ent2 != NULL);

    // Make an array of AcDbObjectIds from the

    // insertStack. Don’t use the "smart array"

    // AcDbObjectIdArray class, because the

    // getSubentPathsAtGsMarker() function expects argument

    // eight to be of type AcDbObjectId*. Just

    // make room for approximately 100 IDs in the array.

    //

    AcDbObjectId *idArray = new AcDbObjectId[100];

    int count = 0;


    struct resbuf *rbIter = insStack;

    AcDbObjectId objId;

    acdbGetObjectId(objId, ename);

    idArray[count++] = objId;

    while (rbIter != NULL) {

    ename[0] = rbIter->resval.rlname[0];

    ename[1] = rbIter->resval.rlname[1];

    acdbGetObjectId(objId, ename);

    idArray[count++] = objId;

    rbIter = rbIter->rbnext;

    }

    count--;

    acutRelRb(insStack);

    // First, we’ll highlight an edge.

    //

    int numPaths;

    AcDbFullSubentPath *subentPaths;

    AcGeMatrix3d xform;

    es = blRef->getSubentPathsAtGsMarker(

    AcDb::kEdgeSubentType,

    marker,

    pickpnt,

    xform,

    numPaths,

    subentPaths,

    count,

    idArray);

    assert(numPaths == 1);

    // Highlight and unhighlight the selected edge.

    //

    acutPrintf("\nHighlighting the first edge.");

    es = blRef->highlight(subentPaths[0]);

    pressEnterToContinue();

    es = blRef->unhighlight(subentPaths[0]);

    // If this is a solid, it will have faces.

    // In this case, let’s highlight them.

    //

    if(ent2->isKindOf(AcDb3dSolid::desc())) {

    es = blRef->getSubentPathsAtGsMarker(

    AcDb::kFaceSubentType,

    marker,

    pickpnt,

    xform,

    numPaths,

    subentPaths,

    count,

    idArray);

    assert(numPaths == 2);

    // Highlight and unhighlight the selected

    // faces.

    //

    acutPrintf("\nHighlighting the first"

    " face.");

    es = blRef->highlight(subentPaths[0]);

    pressEnterToContinue();

    es = blRef->unhighlight(subentPaths[0]);

    acutPrintf("\nHighlighting the next face.");

    es = blRef->highlight(subentPaths[1]);

    pressEnterToContinue();

    es = blRef->unhighlight(subentPaths[1]);

    }

    delete []subentPaths;

    // Now, let’s highlight the whole entity.

    //

    acutPrintf("\nHighlighting the entire entity");

    AcDbFullSubentPath subPath;

    for (int i = count; i >= 0; i--) {

    subPath.objectIds().append(idArray[i]);

    }

    es = blRef->highlight(subPath);

    pressEnterToContinue();

    es = blRef->unhighlight(subPath);

    // Finally, let’s highlight each enclosing

    // insert.

    //

    for (i = count -1; i >= 0; i --) {

    subPath.objectIds().removeAt(

    subPath.objectIds().length() - 1);

    acutPrintf("\nHighlighting insert layer %d",

    i + 1);

    blRef->highlight(subPath);

    pressEnterToContinue();

    es = blRef->unhighlight(subPath);

    }

    } // case RTNORM

    break;

    case RTNONE:

    case RTCAN:

    return;

    default:

    continue;

    } // switch

    break;

    } //for (;;)

    AOK(ent->close());

    AOK(ent2->close());

    return;

    }

    Взаимодействие с AutoCAD

    Взаимодействие Пользователя (типа acedGetPoint) от запроса Автоматизации должно быть обернуто вокруг ряда ObjectARX ВЫЗОВОВ API. Это позволяет Вам сохранять AutoCAD “состояние” перед взаимодействием и затем восстанавливать это впоследствии. Это также гарантирует, что любой другой из -процесса запросы Автоматизации отклонены для продолжительности вашего взаимодействия. Это предотвращает другого клиента Автоматизации от изменения командной строки или базы данных, в то время как Вы ожидаете ввод пользователя.
    ObjectARX API, чтобы использовать при взаимодействии с пользователем включают следующие функции:
    Adesk::Boolean acedSetOLELock(int handle, int flags=0);
    Adesk::Boolean acedClearOLELock(int handle);
    void acedPostCommandPrompt();
    Например:
    // Получить точку в AutoCAD, даже при том, что точка не используется.
    //
    STDMETHODIMP CMyApp::GetPoint()
    {
    // Установление блокировки сообщает AutoCAD, чтобы отклонить любой другой из -процесса запросы
    // Автоматизации. Если этот запрос сделан от неизвестного контекста (например, не нормалью AutoCAD
    // зарегистрированной командой или lisp), то это также сохраняет поток состояние AutoCAD.
    //
    if (acedSetOLELock(5) != Adesk::kTrue)
    {
    return E_FAIL;
    }
    // Do the input acquisition (interaction) ==  Делайте входное приобретение (взаимодействие).
    //
    ads_point result;
    if(ads_getpoint(NULL, "Pick a point: ", result) != RTNORM)
    {
    return E_FAIL;
    }
    // Clear the lock to allow out-of-process Automation
    // requests to be accepted again. If the AutoCAD state was saved
    // during the call to acedSetOLELock(), then the saved state is
    // restored.
    // Очистить блокировку, чтобы позволить из -процесса запросам Автоматизации быть принятым
    // снова. Если состояние AutoCAD было сохранено в течение запроса к acedSetOLELock (), то
    // сохраненное состояние восстановлено.
    //
    acedClearOLELock(5);
    //Вынуждает AutoCAD восстанавливать изображение приглашения ко вводу команды..
    //
    acedPostCommandPrompt();
    return S_OK;
    }

    WblockClone ()

    Имеются три версии AcDbDatabase:: wblock ():
    1 WBLOCK*
    Acad:: ErrorStatus
     AcDbDatabase::wblock(AcDbDatabase*& POutputDatabase)
    2 WBLOCK определяемого пользователем блока
    Acad:: ErrorStatus
     AcDbDatabase::wblock(AcDbDatabase*& POutputDatabase, AcDbObjectId nObjId)
    3 WBLOCK набора выборов
    Acad:: ErrorStatus
     AcDbDatabase::wblock(AcDbDatabase*& POutputDatabase, const AcDbObjectIdArray& PIdSet, const AcGePoint3d& PPoint3d)
    Одно из основных внутренних различий между этими тремя версиями wblock - их обработка пространства модели и пространства листа AcDbBlockTableRecords. Поскольку полная база данных клонируется в одной версии, все примитивы в пространстве модели и пространстве листа клонированы наряду с их содержащей бумагой и пространством модели AcDbBlockTableRecords. Однако, в версиях два и три, намерение должно клонировать только отобранный набор примитивов. Хотя пространство модели и пространство листа AcDbBlockTableRecords обработаны, они используют “ поверхностный клон, ”, который в свою очередь не клонирует все примитивы, содержащиеся в пространстве модели и пространстве листа.
    Даже при том, что пространство модели и блоки пространства листа были клонированы в версиях два и три, они пусты. Поэтому, не только приемлемо вызвать AcDbBlockTableRecord:: AppendAcDbEntity () чтобы разместить клонированные примитивы в них, необходимо делать так. (Это - исключение к использованию AcDbBlocKTableRecord:: AppendAcDbEntity () на AcDbBlockTableRecords, чей ID - в состоянии непрерывного изменения). Также, в обеих версиях два и три, примитивы будут иметь набор isPrimary к Adesk:: kTrue, когда они получают их wblockClone () запрос.
    Это - то, потому что внутренний код индивидуально клонирует примитивы набора выборов, или примитивов отобранного AcDbBlockTableRecord. Это не клонирует AcDbBlockTableRecord непосредственно. (Примитивы во вложенных блоках, однако, будут все еще иметь набор isPrimary к Adesk:: kFalse). Это поведение полезно, как будет замечено в следующей секции в случае 1. Это сохраняет приложения от необходимости знать, что какая операция WBLOCK встречается.
    Имеются несколько основных правила, чтобы иметь в виду:
    1 Никогда не использовать AcDbBlocKTableRecord::AppendAcDbEntity() в течение WBLOCK*. Если Вы создали новые примитивы, Вы должны сохранить их в памяти, наряду с ID их будущего владельца, и затем добавлять их после AcEdItorReactor::endDeepClone(). Это также применяется к добавлению в конец объектов к AcDbDictionaries, ломаным линиям, polyfacemeshes, polygonmeshes, и блок-ссылкам.
    2 В других двух формах WBLOCK, только используют AcDbBlocKTableRecord::ApPendAcDbEntity() при добавлении в конец к пространству модели или пространству листа. Но с тем исключением, все другие ограничения, упомянутые для WBLOCK* все еще применяются.

    WhipView

    WhipView библиотечные орудия AcGixView и AcGixVectorTaker на
    вершине WHIP! Графический акселератор. WHIP! Является графическим акселератором с 2-ым кэшем изображения, сформированным на вершине HEIDI технологии Autodesk. Это экспортирует единственную функцию API, acgixAllocateWhipView (), который создает и возвращает образец AcGixBlockView. Возвращенный образец может использоваться таким же образом как любой другой AcGixBlockView. SimpleView библиотека демонстрирует создание рисунка видов, использующих WhipView. Из-за дисплейного файла, WhipView способен обслужить некоторые действия подобно кастрюле и изменять масштаб изображения без потребности в перегенеральном. Это дает лучшее работу, чем прямое выполнение GDI SimpleView.
    WhipView снабжен в двоичной форме только, и состоит из несколько DLLs и файлах поддержки, представляющих WhipView библиотеку, WHIP! Компонент, HEIDI, и HDI драйверы устройства. WhipView может использоваться независимым от SimpleView, если бы не необходимые элементы AcGixBlockView. Прямое использование WHIP!, HEIDI, и HDI драйверы ObjectDBX разработчиками не поддержан.
    Они снабжены в двоичной форме только, без связанных заголовков.
    API WhipView модуля состоит из единственной точки входа, которая имеет следующую сигнатуру:
    AcGixBlockView* acgixAllocateWhipView ();
    Эта функция явно объявлена внешней и используется в SimpleView исходном модуле AcGixSimpleViewManager.cpp. Не имеется никакого экспортируемого файла заголовка, который объявляет acgixAllocateWhipView ().
    Чтобы многократно использовать этот элемент, Вы должны брать AcGixBlockView, столь же определенный и так много еще SimpleView комплекса, что необходимо. Быть Предупредите, однако, что AcGixBlockView довольно усложнен и использует многое из остальной части SimpleView. Выполнение наиболее легко сделано, если Вы оставляете SimpleView в по существу неизменном состоянии.
    WhipView клиенты связываются непосредственно с AcGixWhipView.lib. WhipView требует AcDb.dll, heidi3.dll, dllong3.dll, и HDI файлы, снабженные в каталоге выпусков.

    BAT файл пользователя, чтобы включить

    Вы должны модифицировать AUTOEXEC. BAT файл пользователя, чтобы включить “aliased” (или короткий) имя пути, потому что переменная ПУТИ не будет обрабатывать пробелы. В то время как пути к приложению должны удовлетворить, строго рекомендуется, чтобы Вы модифицировали пользователя AUTOEXEC.BAT из-за известных проблем с автоматизацией (отнесите к Microsoft KnowledgeBase статью Q148375).

    Гарантируйте умные модификации путей

    При модифицировании пользователя AUTOEXEC.BAT пожалуйста, быть прилежный относительно изменения входа пути, если вход пути - уже там. Что должно быть предотвращено,  только изменяет ПУТЬ без отношения к любому из этих условий:

    §

    путь - уже там.

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

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

    Autodesk обеспечивает сценарий InstallShield ниже как неполный пример сильного модифицирования пути:

    function AdUpdateAUTOEXEC (szSharedPath)

    STRING szRootPath, szBatchName, szBatchFile,

    szBackupName,szTestLine,szCheckForPathLine;

    NUMBER nReturn, nvHandle;

    STRING szOutput;

    begin

    szOutput = "SET PATH=%PATH%;" + szSharedPath;

    // Obtain the filename of the system batch file.

    BatchGetFileName (szBatchFile);

    ParsePath(szRootPath, szBatchFile, PATH);

    // Make sure we’re pointing at the root of the system

    VarSave(SRCTARGETDIR);

    TARGETDIR = szRootPath;

    SRCDIR = szRootPath;

    // See if we have an AUTOEXEC.

    if (Is(FILE_EXISTS,szBatchFile) = FALSE) then

    // If we don’t, just write ’ours’ out and no more

    OpenFileMode (FILE_MODE_NORMAL);

    ParsePath(szBatchFile,szBatchFile,FILENAME);

    CreateFile (nvHandle,SRCDIR,szBatchFile);

    WriteLine (nvHandle, szOutput);

    CloseFile (nvHandle);

    bNeedReboot = TRUE;

    else

    ParsePath(szBatchName, szBatchFile, FILENAME_ONLY);


    szBackupName = szBatchName + ".ADK";

    ParsePath(szBatchFile, szBatchFile, FILENAME);

    OpenFileMode(FILE_MODE_NORMAL);

    nReturn = OpenFile (nvHandle, SRCDIR, szBatchFile);

    if (nReturn = 0 ) then

    // Spin down to find the non-blank last line in

    // the file

    while (nReturn = 0 )

    nReturn = GetLine(nvHandle, szTestLine);

    if (StrLength(szTestLine) > 0) then

    szCheckForPathLine = szTestLine;

    endif;

    endwhile;

    CloseFile(nvHandle);

    // We now have the last text entry in the batch

    // file.

    if (StrFind(szCheckForPathLine,szSharedPath) < 0) then

    Disable(LOGGING);

    // Backup up the original

    nReturn = CopyFile (szBatchFile, szBackupName);

    Enable(LOGGING);

    if (nReturn = 0 ) then

    OpenFileMode (FILE_MODE_APPEND);

    OpenFile(nvHandle,SRCDIR,szBatchFile);

    WriteLine(nvHandle,"");

    WriteLine(nvHandle,szOutput);

    CloseFile(nvHandle);

    bNeedReboot = TRUE;

    endif;

    endif;

    endif;

    endif;

    VarRestore(SRCTARGETDIR);

    end;

    WorldDraw () Функция

    WorldDraw() функция - первичный механизм для drawable, чтобы отобразить себя. От этого повторного вызова drawable использует AcGiSubEntityTraits и интерфейсы AcGiWorldGeometry, чтобы сообщить AcGi
    выполнение, как этот drawable должен быть представлен во всех активных областях просмотра. Для информации, которая является определенной к некоторым областям просмотра, viewportDraw () повторный вызов обеспечивается (см. “ viewportDraw () Функцию ” на странице 688).
    AcDbEntity:: worldDraw () функция берет указатель на объект AcGiWorldDraw. AcGiWorldDraw - контейнерный класс для AcGi геометрии и объектов черт. Определенно, AcGiWorldDraw содержит два других объекта:
    §
    AcGiWorldGeometry
    § AcGiSubEntityTraits
    К  объекту AcGiWorldGeometry можно обращаться изнутри worldDraw() используя AcGiWorldDraw::geometry(), к объекту  AcGiSubEntityTraits можно обращаться,  используя AcGiWorldDraw::subEntityTraits().
    Объект AcGiWorldGeometry записывает векторы на дисплей AutoCAD, использующий его набор рисунка примитивов. Примитив - команда с  самым низким уровнем, имел обыкновение рисовать графические примитивы. Мировой объект геометрии имеет следующие функции для рисунка примитивов в мировых координатах, которые унаследованы от AcGiGeometry:
    § Circle
    § Circular arc
    § Polyline
    § Polygon
    § Mesh
    § Shell
    § Text
    § Xline
    § Ray
    § Draw
    Рисующий метод позволяет Вам определять другой drawable, который нужно использовать как часть вашей геометрии. Это могло бы быть другой примитив или в оперативной памяти drawable.
    AcGi использует тот же самый setAttributes (), worldDraw (), и viewportDraw () логика на этом объекте, поскольку это использует на вашем объекте.
    Объект AcGiSubEntityTraits устанавливает графические атрибуты со значением, использующие его набор функций черт:
    § Color
    § Layer
    § Linetype
    § Polygon fill type
    § Selection marker
    § Line weight (вес Линии)
    § Thickness (Толщина)
    § Графическое имя стиля (не должен измениться в течение worldDraw () или viewportDraw ())

    Xrecord Объекты

    Xrecord объект - встроенный объектный класс с именем DXF “XRECORD”, который сохраняет и управляет произвольными потоками данных, представ внешне в результате буферизуют список, составленный из групп DXF с “ объект нормали ” группы (то есть не - xdata коды группы), в пределах от 1 до 369.
    ПРЕДУПРЕЖДЕНИЕ! Xrecord объект разработан{*предназначен*} в пути, который не будет оскорблять более ранние версии AutoCAD; однако, xrecord объект исчезнет при создании DXF файла от предварительного выпуска 13c4 уровень AutoCAD.
    Xrecord объекты - универсальные объекты, предназначенные для использования приложениями ObjectARX и AutoLISP. Этот класс позволяет приложениям создавать и сохранять произвольные объектные структуры произвольных списков буфера результата не-графической информации, полностью отделяются от примитивов. Корневой владелец для всех определенных приложением объектов является или словарью имен объектов, которая принимает любой тип AcDbObject как вход, включая AcDbXrecord, или словарь расширения любого объекта.
    Приложения, как ожидается,  будут использовать уникальные названия{*имена*} входа в словари имен объектов. Логика использования словари имен объектов или имени входа словаря расширения{*продления*} подобна таковому имени REGAPP. Фактически, REGAPP названия{*имена*} совершенен для использования как названия{*имена*} входа при добавлении в конец определенных приложением объектов к базе данных или специфическому объекту.
    Использование xrecord объектов представляет существенное упрощение относительно текущей практики назначения xdata к примитивам. Поскольку xrecord объект не должен быть связан с примитивом, Вы больше не должны создать фиктивные примитивы (фиктивные примитивы часто использовались, чтобы обеспечить большее количество участка памяти для xdata), или примитивов на закрепемых уровнях.
    Приложения теперь способны делать следующее:
  • Защищают информацию от неразборчивой чистки или размораживания уровней, который является всегда угрозой неграфической информации, сохраненной в data.


  • Используют новые поля (330-369 ссылки / указателя монопольного использования объекта, чтобы обслужить{*поддержать*} внутренние ссылки объекта базы данных. Произвольные значения метки полностью освобожденны от механики трансляции объекта ID. Это оппозиционно настроено в отношении 1005 xdata групп, которые оттранслированы в некоторых случаях, но не в других.


  • Остаются незатронутым 16КБ в объект xdata предел способности{*вместимости*}. Этот объект может также использоваться вместо xdata на определенных примитивах и объектах, если один так пожелания, с пониманием, что независимо от того, где Вы сохраняете xrecord объекты, они не имеют никакого встроенного предела размера, другого чем предел 2 ГБАЙТА, наложенных подписанным 32-разрядным целочисленным диапазоном.


  • В случае объектно - определенного состояния, xrecord объекты хорошо удовлетворены для сохранения больших количеств сохраненной информации, в то время как xdata лучше удовлетворенный для меньших количеств данных.

    При монтаже иерархии xrecord объектов (добавление монопольного использования или ссылки указателя к объекту), тот объект должен уже существовать в базе данных, и, таким образом, иметь законное имя примитива. Поскольку acdbEntMake () не возвращает имя примитива, и acdbEntLast () только признает графические объекты, Вы должны использовать acdbEntMakeX () если Вы ссылаетесь на неграфические объекты.

    AcdbEntMakeX () функция возвращает имя примитива объекта, добавленного к базе данных (или графический или неграфический). Начальный Выпуск 13 выполнения acdbEntMake () только поддержанные объекты, чей класс диктовал его определенный объект контейнера владельца в текущем рисунке (типа входов таблицы идентификаторов, весь снабженный Выпуск 13 типов примитива, и объекты словаря), и зарегистрировал новый объект с его владельцем. Эти функции продолжат делать это для того же самого набора встроенных объектных классов, включая примитивы. Для xrecords и всех классов пользователя, эти функции добавят объект к базе данных, оставляя это до приложения, чтобы установить его связи{*ссылки*} монопольных использований снова до словари имен объектов. AcdbEntMakeX () функция добавляет объект к базе данных для всех типов объекта, включая,  которые идут С AutoCAD. Так, даже при использовании этой функции на существующих типах примитива, ваша программа ответствена за установку монопольного использования.

    Xrecords

    Xrecords дают возможность Вам добавить произвольные, специфические для приложения данные. Поскольку они - альтернатива к определению вашего собственного объектного класса, они особенно полезны для программистов AutoLISP. Xrecord - образец класса AcDbxrecord, который является подклассом AcDbObject. Xrecord государство{*состояние*} определен как содержание resbuf цепочки, которая является списком групп данных, каждая из которых в свою очередь содержит код группы DXF плюс связанные данные. Значение кода группы определяет связанный тип данных. Коды Группы для xrecords находятся в диапазоне от 1 до 369. Следующий раздел описывает доступную группу DXF коды.
    Не имеется никакого свойственного предела размера на сумму данных, которые Вы можете сохранять в record. Xrecords может принадлежать любому другому объекту, включая словарь расширения{*продления*} любого объекта, словари имен объектов, любого другого словаря, или другого xrecords.
    Никакое уведомление не послано, когда xrecord изменяется. Если приложение должно знать, когда объект, имеющий xrecord изменился, приложение будет должно послать его собственное уведомление.
    AcDbXrecord класс обеспечивает две функции члена для установки и получения resbuf цепочками, setfromRbChain () и rbChain () функциями:
    Acad::ErrorStatus
    AcDbXrecord::setFromRbChain(
    resbuf& pRb,
    AcDbDatabase* auxDb=NULL);
    Acad::ErrorStatus
    AcDbXrecord::rbChain(
    resbuf** ppRb,
    AcDbDatabase* auxDb=NULL) const;
    AcDbXrecord:: setFromRbChain() функция заменяет существующую resbuf цепочку .

    Загрузка ObjectARX Приложения

    Вы можете загружать приложение ObjectARX, используя любой из следующих методов:
  • Обеспечивают приложение особенностями, которые позволяют этому быть запросом, загруженным в соответствии с AutoCAD. Эти особенности включают специфические для приложения входы в Windows NT (или Windows ® 95) системный реестр. См. “ Загрузка Запроса ” на странице 45.

  • Определяют приложение в начальном файле модуля, acad.rx. Этот файл содержит текст ASCII с именами всех программ AutoCAD, должен загрузиться, когда это начато. Каждая строка в файле содержит название программы (с путем, если файл не в каталоге на пути поиска файлов библиотеки AutoCAD). Acad.rx файл должен также быть в каталоге на пути поиска файлов AutoCAD.

  • Делают прикладной запрос загрузки от другого приложения ObjectARX, используя AcRxDynamicLinker:: loadModule ().

  • Используют диалоговое окно APPLOAD, определенное в премии AutoCAD, программируют loadapp.arx.

  • Используют arxload () функция от АвтоЛисп.

  • Используют acedArxLoad () функция от ObjectARX.

  • Вводят команду ARX в командную строку AutoCAD и используют опцию Load.


  • Загрузка по требованию

    Требование, загружающее механизм - по существу тот же самый для приложения ObjectDBX, поскольку это - для ObjectARX-приложения. Единственное различие находится в том, где информация найдена в системном реестре. Для требования, загружающего ObjectARX-приложения, AutoCAD смотрит в системном реестре системы под следующим:
    HKEY_LOCAL_MACHINE
    Software
    Autodesk
    AutoCAD
    R15.0
    ACAD-xxxxxxx-xxxxxxxx
    Applications
    xxxxxxx-xxxxxxxx  является номером, уникальным к каждой инсталляции.
    Для требования загружающего приложения DBX, ObjectDBX будет смотреть в системном реестре системы под следующим:
    HKEY_LOCAL_MACHINE
    Software
    Autodesk
    ObjectDBX
    R15.0
    Applications
    Они - жестко закодированные ключи и - тот же самый для любого приложения на любой машине. Ваша прикладная информация идет при входе Приложений.

    Загрузка по запросу

    Загрузка Запроса - особенность AutoCAD, который автоматически пытается загружать приложение ObjectARX, которое - не резидент в AutoCAD. Приложения ObjectARX могут быть предназначены для загрузки в соответствии с AutoCAD под одним или большим количеством следующих обстоятельств:
    · когда читается чертежный файл, который содержит заказные объекты, созданные отсутствующим приложением; 
    · когда пользователь или другое приложение выпускает одну из команд отсутствующего приложения;
    · когда AutoCAD начат;
    ОБРАТИТЕ ВНИМАНИЕ На приложения, которые осуществляют загрузку запроса на запуске AutoCAD, будет загружен прежде, чем перечисляли в acad.rx.
    AutoDesk рекомендует разработать приложения ObjectARX, которые воспользуются преимуществом загружающей запроса особенности AutoCAD потому что загрузка запроса, обеспечивая следующие выгоды:
    · Ограничивает создание полномочных объектов (см. главу 14, “ Полномочные Объекты”)
    · Обеспечивает большую гибкость для загрузки приложений ObjectARX
    · Сохраняет память,  загружая приложения только, когда их функциональные возможности требуются
    Для приложения, чтобы быть доступный для загрузки запроса, специфическая для приложения информация должна присутствовать в системном реестре системы Windows. Кроме того, Приложения ObjectARX с больше чем один DLL могут нуждаться в модуле “контроллера”, который является ответственным за загрузку всех других компонентов
    Приложение. Наконец, DEMANDLOAD системная переменная должна быть установлена в соответствующее значение для загрузки запроса.
    ОБРАТИТЕ ВНИМАНИЕ, что приложение ObjectARX может быть запрос, загруженный от пути на местной машине, или,  используя адрес Internet.

    Загрузка Запроса на Команде

    AutoCAD будет пытаться загружать соответствующее Приложение ObjectArx, если пользователь вызывает команду, которая не зарегистрирована с AutoCAD.
    Чтобы поддерживать загрузку запроса на обращении команды, программа инсталляции приложения ObjectARX должна создать соответствующие клавиши{*ключи*} и значения в системном реестре для команд приложения. Раздел приложения Commands системного реестра должен содержать информацию команды подобно этому:
    \\ HKEY_LOCAL_MACHINE\SOFTWARE\
    Autodesk\ ...
    ...
    PolySampInc\polysamp\
     Loader\MODULE:REG_SZ:c:\polysampinc\arx\polyui.arx
    Name\PolySamp:REG_SZ:PolyCad
    Commands\
    ASDKPOLY:REG_SZ:ASDKPOLY
    ASDKDRAGPOLY:REG_SZ:ASDKDRAGPOLY
    ASDKPOLYEDIT:REG_SZ:ASDKPOLYEDIT
    Groups\
    ASDK:REG_SZ:ASDK
    ...
    В этом примере, зарегистрированный префикс разработчика разработчика (ASDK) используется как префикс для всех команд, чтобы гарантировать, что не будет иметься никакого возможного конфликта с командами того же самого названия{*имени*} в других приложениях.
    Приложение ObjectArx должно также включить соответствующие запросы к acedRegCmds макрокоманде для загрузки запроса на команде, чтобы работать.

    Загрузка Запроса на Обнаружении Заказных Объектов{*целей*}

    Когда DWG или DXF файл, содержащий заказные объекты загружен, AutoCAD определяет, действительно ли приложение - обработчик загружено. Если приложение не загружено, и первый бит переменной системы DEMANDLOAD установлен, AutoCAD ищет системный реестр системы Windows информацию относительно приложения и его модуля загрузчика. Если AutoCAD находит соответствующую информацию в системном реестре, это загружает приложение.
    ОБРАТИТЕ ВНИМАНИЕ, что загрузка Запроса на обнаружении заказных классов будет только работать с классами, которые получены из AcDbObject, или непосредственно или косвенно.
    Как гипотетический пример, давайте предполагать, что AutoCAD читает файл, созданный Приложением ObjectArx polysamp (изделие{*программа*} PolySamp компании).
    1 После чтения чертежного файла, AutoCAD сталкивается с заказными объектами{*целями*}, созданными с приложением polysamp, и решает, что приложение не загружено.
    2 AutoCAD находит, что DEMANDLOAD системная переменная установлена, чтобы допустить загрузке запроса приложений на полномочном обнаружении, так что это ищет раздел Приложений AutoCAD системного реестра для polysamp клавиши{*ключа*}.
    В пределах этой клавиши{*ключа*}, это находит значение LoadCtrls, которое определяет условия{*состояния*}, при которых приложение должно быть загружено, и значение RegPath, которое обеспечивает полный путь системного реестра для polysamp модуля. Этот раздел системного реестра смотрел бы кое-что вроде этого:
     \\HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R15.0\
    ACAD-1:409\
    Applications\PolyCAD\
    LoadCtrls:REG_DWORD:0xd
    RegPath:REG_SZ:
     \\HKEY_LOCAL_MACHINE\SOFTWARE\PolySampInc\polysamp
    3 AutoCAD читает polysamp\Loader клавишу{*ключ*}, чтобы определить каталог, путь, и имя файла модуля, который будет загружен. Этот раздел каталога смотрел бы кое-что вроде этого:
    \\ HKEY_LOCAL_MACHINE\SOFTWARE\
    PolySampInc\polysamp\
     Loader\MODULE:REG_SZ:c:\polysampinc\arx\polyui.arx
    Name\PolySamp:REG_SZ:PolyCad
    4 AutoCAD тогда пытается загружать ObjectARX модуль. Если загрузки модуля успешно, AutoCAD прибавляет маркер{*дескриптор*} приложения к списку прикладных маркеров{*дескрипторов*}, которые будут посланы kLoadDwgMsg сообщение. AutoCAD тогда подтверждает{*проверяет*}, что приложение было загружено должным образом, и подтверждает{*проверяет*}, что заказной класс зарегистрирован. Если приложение было загружено успешно, AutoCAD продолжится
    Загружать чертежный файл. Если ObjectARX модуль не может быть загружен, или если все еще не имеется выполнения класса, доступные, заказные объекты{*цели*} обработаны как proxies, и загрузка продолжается.

    Загрузка Запроса на Запуске AutoCAD

    Загрузка Запроса Приложения ObjectArx на запуске AutoCAD может быть определена,  используя 0x02 (или Вы можете исполнять ИЛИ 0x02 с другим законным значением) со значением LoadCtrls в системном реестре, как показано здесь.
     \\HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R15.0\
    ACAD-1:409\
    Applications\PolyCAD\
    LoadCtrls:REG_DWORD:0x02
    RegPath:REG_SZ:
    Управление Приложениями с Системным реестром
    Как только системная информация системного реестра была создана для загрузки запроса, что та же самая информация может использоваться набором функций ObjectARX, чтобы загружать, разгрузить, и контролировать присутствие Приложений ObjectArx, независимых от загружающей запроса особенности. Параметр AppName, используемый первой двумя из этих функций - логическое прикладное название{*имя*}.
    Следующие функции ObjectARX могут использоваться с зарегистрированными прикладными названиями{*именами*}:
    Bool acrxLoadApp ("AppName")
    Эта функция берет одиночный параметр, который представляет случай{*регистр*} -нечувствительное логическое название{*имя*} приложения, которое будет загружено. Функция возвратилась бы 0, если загрузка потерпела неудачу, или 1, если загрузка преуспевает.
    Bool acrxUnloadApp ("AppName")
    Эта функция берет одиночный параметр, который представляет случай{*регистр*} -нечувствительное логическое название{*имя*} приложения, которое было предварительно загружено. Функция возвращается 0, если разгруженные сбои, или 1, если это преуспевает.
    Пусто *acrxLoadedApps ()
    Эта функция возвращает массив строк как пустой *, содержа логическое прикладное название{*имя*} каждого приложения, которое в настоящее время загружено. Функциональные возвращения ПУСТОЙ УКАЗАТЕЛЬ, если никакие приложения не загружены. Это - ответственность вызывающей программы выпустить пространство{*пробел*}, распределенное для возвращенных строк.

    Заказные режимы объектной привязки

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

    Запись Объекта в файл

    Запись в файл Объекта обращается{*относится*} к конверсионному процессу между государством{*состоянием*} объекта и одиночной последовательностью данных, для целей типа сохранения этого на диске, копирование этого, или регистрации его государства{*состояния*} для операции отмены. Запись в файл из иногда называется, преобразовывая в последовательную форму.
    Запись в файл объекта в - процесс превращения последовательности данных назад в объект, иногда называемый deserializing.
    Запись в файл используется в нескольких контекстах в AutoCAD:
  • Запись и чтение DWG файлы (использует формат DWG)

  • Запись и чтение DXF файлы (использует формат DXF)

  • Сообщающий среди AutoCAD, AutoLISP, и ObjectARX (использует формат DXF)

  • регистрация Отмены и восстановление (использует формат DWG)

  • операции Copying типа ВСТАВКИ, ТАБЛИЦЫ ПЕРЕКРЕСТНЫХ ССЫЛОК, и КОПИИ (использует формат DWG)

  • Листание (использует формат DWG)

  • AcDbObject имеет две функции элемента для записи в файл из: dwgOut () и dxfOut (), и две функции элемента для записи в файл в: dwgIn () и dxfIn ().
    Эти функции элемента прежде всего называются в соответствии с AutoCAD; запись в файл объекта почти никогда явно не управляется приложениями, которые используют базу данных.
    Однако, если ваше приложение осуществляет новые классы объекта базы данных, вы будете нуждаться в более глубоком понимании объектной записи в файл. См. главу 12, “ Происходящий от AcDbObject. ”
    Dwg- и dxf- префиксы указывают два существенно различных формата данных, первый типично используемый в письменной форме к и от DWG файлов, и второй прежде всего для DXF файлов и AutoLISP entget, entmake, и функций entmod. Первичное различие между двумя форматами - то, что для DWG регистраторов (объект, который записывает, данные к файлу), данные явно не отмечены.
    DXF регистраторы, напротив, присоединяют код группы данных с каждым элементом данных в изданном формате данных (см. главу 12, “ Происходящий от AcDbObject ”).

    Запросы AutoCAD и функции Команды

    Следующие функции AutoCAD не могут быть вызваны, в то время как диалоговое окно активно:
    § acedCommand ()
    § acedCmd ()
    § acedHelp ()
    § acedOsnap ()

    Жесткие Указатели

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

    Жесткое Монопольное использование

    Следующее - три примера жесткого монопольного использования:
    §
    объект базы данных - жесткий владелец его словаря расширения{*продления*}.
    § блочная таблица - жесткий владелец образцовых пространственных и бумажных пространственных блочных отчетов{*записей*} таблицы (но не другие блочные отчеты{*записи*} таблицы).
    § словари Расширений{*продления*} - жесткие владельцы их элементов.

    Значение Уровня Базы данных

    Следующий набор функций устанавливает и восстанавливает текущее значение уровня в базе данных:
    Acad::ErrorStatus
    AcDbDatabase::setClayer(AcDbObjectId);
    AcDbObjectId AcDbDatabase::clayer() const;

    Значения причины Повторного вызова



    Код

     Символ

     Описание

    1

     CBR_SELECT

    Пользователь выбрал неперекрывающее расположение. Это - значение для большинства неперекрывающих расположений действия.

    2

     CBR_LOST_FOCUS

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

    3

     CBR_DRAG

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

    4

    CBR_DOUBLE_CLICK

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

    Значение двойного щелчка на списке или кнопке изображения - до вашего приложения. Если основная цель диалогового окна состоит в том, чтобы выбрать элемент списка, двойной щелчок должен делать выбор и затем выходить из диалогового окна (в этом случае, атрибут is_default list_box неперекрывающего расположения должен быть истинен). Если список - не первичное неперекрывающее расположение в диалоговом окне, то с двойным щелчком нужно обращаться с тем же самый как создание выбора (1, или CBR_SELECT). Списки, которые позволяют пользователю выбирать множественные элементы (multiple_select = истина;) не может поддерживать двойное нажатие.
    Если основная цель диалогового окна состоит в том, чтобы выбрать кнопку изображения, одиночный щелчок должен выбрать кнопку, но иногда это лучше для одиночного щелчка (или перемещение клавиатуры) чтобы высветить кнопку и ENTER или двойной щелчок, чтобы выбрать это.
    Пример обработки кнопки изображения одиночного щелчка - диалоговое окно AutoCAD Choose Hatch Pattern (вызванный от команды BHATCH). Пример кнопок изображения двойного щелчка - диалоговое окно AutoCAD Select Text Font (вызванный от опции Set Style на Текстовом подменю по умолчаниюа, рисуют опускающееся меню), который показывает список с текстовыми названиями стиля и кнопками изображения с эквивалентными текстовыми значками стиля. В этом диалоговом окне, одиночный щелчок или на кнопке изображения или элементе списка высвечивает, и текстовое имя стиля и значок, и двойной щелчок на любом делает выбор.

    Значения Списка Обработки

    Значение list_box поля ввода может содержать ведущие пробелы. Если Вы отыскиваете множественные элементы, не проверите значение как строковое сравнение. Преобразуйте это к целому числу сначала, используя atoi ().
    Принимая, что список принимает только единственный выбор, следующие проверки фрагмента кода был ли третий список элемент отобран. (Убедитесь, что строка пуста первая, потому что atoi () возвращается 0 для пустой строки также как для строки “0”.) следующий пример использует значение, прошел в пакете повторного вызова:
    if (*cpkt->value != EOS) {
    if ((atoi(cpkt->value) == 2) {
    // Process the third entry.
    ...
    }
    }
    Значение всплывающего списка никогда не имеет ведущее пространство, так что Вы не должны преобразовать значение. Всплывающие списки не позволяют множественный выбор.
    Если список поддерживает множественный выбор, ваша программа должна делать преобразование и шаг через множественные значения в строке значения. Следующий пример требует, чтобы Вы включили файл заголовка стандартной библиотеки для C string.h.
    Кроме того, Вы должны назвать mk_list () функцией со значением потока поля списка, cpkt- >value, и указателем на первоначальный список. Ради простоты, сообщения об ошибках не учтены.
    resbuf
    *mk_list(char *local, struct resbuf *oldlist)
    {
    char spaceset[] = {’ ’, ’\t’, ’\n’}, item[TILE_STR_LIMIT];
    int nitem, i;
    struct resbuf *findrb; *usrlist, *scratch, *usrlast;
    usrlist = usrlast = NULL;
    while (item = strtok(local, spaceset) != NULL) {
    nitem = atoi(item);
    findrb = oldlist;
    for (i=0; i findrb=findrb->rbnext;
    }
    if (usrlist == NULL)  {/*AБ*/  /*  First item */
    if (scratch = acutNewRb(RTSTR) == NULL)
    // Assume it’s a string.
    return NULL;
    if ((scratch->resval.rstring = malloc(strlen(findrb->resval.rstring))) == NULL)
    return NULL;
    strcpy(scratch->resval.rstring, findrb->resval.rstring);
    usrlist = usrlast = scratch;
    } else { /* Trailing items */
    if (scratch = acutNewRb(findrb->restype) == NULL)
    return NULL;
    if ((scratch->resval.rstring =malloc(strlen(findrb->resval.rstring))) ==NULL)
    return NULL;
    strcpy(scratch->resval.rstring, findrb->resval.rstring);
    usrlast->rbnext = scratch;
    usrlast = scratch;
    }
    }
    return usrlist;
    }
    Этот пример также работает для выродившегося случая единственного выбора.

    

        Биржевая торговля: Механические торговые системы - Создание - Программирование