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

и упомянутые примитивы всегда существуют


Если обращение и упомянутые примитивы всегда существуют в том же самом 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();

    }

    }


    Содержание раздела