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

         

Расчленение примитивов


Некоторые примитивы могут взрываемся, или анализир{*расчленен*}, в набор более простых элементов.

Определенное поведение зависит от класса. Например, поля могут взрываемся в области{*регионы*}, затем выравнивают. Ломаные линии могут взрываемся в доли строки. 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 ()):

§         Визуальное появление{*вид*} постоянный.

§         взрываемый примитив стерт от базы данных.

§         Одни или более новые примитивы созданы и добавлены в конец к базе данных.

 



Распечатка Загруженных ObjectARX Приложений


Чтобы видеть названия всех программ ObjectARX, в настоящее время загруженных, используйте опцию команды ARX. Для получения дополнительной информации, см. “ ARX Команду ” на странице 53. Диалоговое окно APPLOAD (определенный в премии AutoCAD программирует loadapp.arx) также перечисляет названия{*имена*} программ ObjectARX, в настоящее время загруженных.



Распространение 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();

}


Расширение Функциональных возможностей Примитива


ObjectARX расширение протокола - гибкий механизм, который может использоваться, чтобы прибавить функциональные возможности к существующим классам ObjectARX во время выполнения. Расширение Протокола позволяет Вам прибавлять функции к существующему классу без того, чтобы переопределить класс и перетранслировать приложение. (См. главу 19, “ Расширение Протокола. ”)

AcDbEntity класс связан с заданным по умолчанию классом расширения протокола, чтобы обеспечить поддержку базового класса для команды MATCHPROP. Заданный по умолчанию класс расширения протокола позволяет Вам копировать цвет, уровень, linetype, и свойства масштаба linetype от одного объекта до другого. Рекомендуется, чтобы AcDbMatchProperties был осуществлены как класс расширения протокола для всех заказных объектов, полученных из AcDbEntity, обеспечивать полную поддержку для MATCHPROP. Если заданный по умолчанию класс расширения протокола перегружен с AcDbMatchProperties, это должно включить функции, чтобы копировать свойства базового класса также.



Расширение протокола для команды MATCH


AcDbMatchProperties - ObjectARX класс, определенно разработанный, чтобы служить как базовый класс расширения протокола, который обеспечивает поддержку примитива для команды MATCHPROP. (См. Ссылку Команды AutoCAD для информации относительно MATCHPROP.) заданный по умолчанию класс расширения протокола для AcDbEntity позволяет копировать цвета, уровня, linetype, и свойств масштаба linetype от одного примитива до другого. Это, однако, предпочтительно осуществить AcDbMatchProperties как класс расширения протокола для всех заказных объектов, полученных из AcDbEntity, обеспечивать полную поддержку для MATCHPROP. Если заданный по умолчанию класс расширения протокола перегружен с AcDbMatchProperties, это должно включить функции, чтобы копировать свойства базового класса также.



Расширение протокола pеализации


Осуществлять расширение протокола

1 Объявляют и определяют классы расширения протокола, которые включают дополнительные функциональные возможности.

2 Регистрируют классы расширения протокола с приложением, и связывают их с классами ObjectARX, к которым они добавляют функциональные возможности.

Эти шаги описаны подробно в следующих двух подразделах. Дополнительная информация относительно проблем выполнения следует за этими секциями.



Расширенные Данные


Расширенные{*продленные*} данные (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);

}


Расширенные данные примитива


Регистрация Расширенных Данных Примитива (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 файле).



Рассмотрение использования памяти


Требования памяти ObjectARX-приложения отличаются от таковых AutoLISP. С одной стороны, структуры данных, используемые программами C++ имеют тенденцию быть более компактными чем списки AutoLISP. С другой стороны, имеется довольно большой, установленный наверху для выполняющихся ObjectARX-приложений.  Часть этого состоит из кода, который должен присутствовать в приложениях непосредственно; большая часть - ObjectARX

библиотека.



Растровые Изображения


Если Вы желаете записать приложение 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 библиотеками.



Размещения


AutoCAD первоначально содержит три размещения: размещение пространства модели и два размещения пространства листа. К этим размещениям можно обращаться позициями табуляции внизу окна рисунка в AutoCAD. Позиции табуляции первоначально названы Моделью, Layout1, и Layout2.

Позиция табуляции Model - заданная по умолчанию позиция табуляции и представляет пространство модели, в котором Вы вообще создаете ваш рисунок. Позиции табуляции Layout1 и Layout2 представляют пространство листа и вообще используются для размещения вашего рисунка для печати. Размещения пространства листа отображают бумажное изображение{*образ*}, которое показывает печатаемой границе для конфигурированного устройства печати.

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



Реакторные Классы


Реакторные классы получены из 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 файлами, Вы должны записывать и читать, вызывает тот же самый заказ{*порядок*}. Если запросы не соответствуют, получены, классы будут перепутаны. Если Вы имеете любые данные переменная-размера, помещаете индекс сначала.



Реализация DXF Файловые Функции


Если Вы осуществляете dxfOutFields () и dxfInFields () для нового класса, ваш полученный класс должен сначала вызвать assertReadEnabled () или assertWriteEnabled (). Это должно тогда назвать ту же самую функцию родительский класс (супер-передачей сообщений).



Реализация Функции точки растяжения


Набор точек растяжения для объекта - часто подмножество его пунктов{*точек*} власти{*захвата*}. Когда пользователь вызывает команду 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



Реализация sampler(), update(), и entity()


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



Реальные преобразования


Файл 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() примитива, передает этому данные матрицы преобразования, и удаляет заказную запись хранения данных от словаря расширения. В действительности, преобразование задержано, пока родительское приложение не присутствует, чтобы применить преобразование к заказному примитиву.



Redo ( Восстановить )


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

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



Регенерация Рисунка


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

effltscale = ent->linetypeScale() * ent->database()->ltscale();

Если PSLTSCALE - 1, эффективный масштаб linetype тогда применяется к появлению{*виду*} образцового пространственного примитива когда рассматривается в бумажном пространстве{*пробеле*}. Если PSLTSCALE - 0, то все масштабирование linetype выполнено относительно образцовых пространственных представлений{*видов*}. См. Руководство программиста AutoCAD для дальнейшего объяснения масштабов linetype.



Регистрация как MDI-ЗНАЮЩИЙ


Приложения, которые встретили{*выполнили*} все эти критерии, должны регистрировать себя как MDI-ЗНАЮЩИЕ в их AcRx:: kInitAppMsg обработчик в acrxEntryPoint (), используя функцию acrxDynamicLinker- > registerAppAsMDIAware (). Приложения, не зарегистрированные как MDI-ЗНАЮЩИЙ не могут быть загружены, когда больше чем один документ открытые. Если такое приложение загружено, дополнительные документы не могут быть открыты.



Регистрация классов расширения протокола


Регистрировать расширение протокола классов с вашим приложением

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 примера в этой главе:



Регистрация Новых Команд


Этот раздел описывает добавляющиеся новые команды, использующие команду AcEdсМеханизм регистрации. Для информации относительно добавления нового использования команд Функции acedDefun() и acedRegFunc (), см. главу 20, “ ObjectARX Глобальные Сервисные Функции. ” Для информации относительно добавления нового использования команд ALisp функция defun, см. Руководство Настройки AutoCAD.



Регистрация Приложения


Прикладные названия сохранены с расширенными данными каждого примитива, который использует их и в 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 внедрять вспомогательные данные (называемый итоговой информацией) в их DWG файлах, и помогает в восстановлении{*поиске*} DWG файлам, основанным на этих данных. Это обеспечивает пользователей AutoCAD поиском файла основного уровня и возможностями управления.

Через Проводник Windows, свойства рисунка могут рассматриваться вне AutoCAD. Использованный вместе с AutoCAD DesignCenter Расширенный Находят особенность, итоговая информация позволяет пользователям искать рисунки, содержащие предопределенные или заказные данные.

AcDbDatabaseSummaryInfo, AcDbSummaryInfoReactor, и классы AcDbSummaryInfoManager обеспечивают API, чтобы работать с итоговой информацией и обсуждены ниже. Для большего количества подробности относительно этих классов, см. ObjectARX Ссылку{*справочники*}.



Руководящие принципы для Использования Фильтрации Точки ввода и Контроля


Чтобы гарантировать хорошее выполнение{*работу*}, сохраните следующие руководящие принципы в памяти при кодировании фильтров точки ввода и мониторов:

§

Будут внимательным относительно выполнения существенного вычисления изнутри фильтров точки ввода и мониторов.

§         Минимизируют число окон вызова разделов, сделанных от фильтров и мониторов.

§         Воспользуются преимуществом доступной работы, которая уже была сделана в соответствии с 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.



SetObjectId ()


Этот метод используется, чтобы выделить, который объект резидентом базы объект COM представляет. Если objId параметр равен AcDbObjectId:: kNull, объект COM проинструктируется, чтобы создать новый объект AcDbObject-derived и добавлять это к базе данных. OwnerId и keyName параметры только определены в этой ситуации.



Шаблоны 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. ”



ShellType


AcBr:: ShellType перечисление классифицирует оболочку как внутренняя область, внешняя область, и так далее.

Периферийные оболочки возвращены как kShellExterior, и имеется только одна такая оболочка в brep или область{*регион*} (в соответствии с соглашением промышленности). Voids возвращены как kShellInterior, и может иметься несколько в brep или комплекс (если имеется также внешняя оболочка).



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

<Selection set: 1>

Тогда следующий типовой код показывает, как 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.”)))



Система координат Дисплея


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



Система координат Глаза


Каждая область просмотра имеет точку преимущества, наклон, цель, и поле вида относительно WCS.

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



Система координат модели


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

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



Система координат Примитива


Если Вы определяете ваш собственный примитив, может быть полезно сохранить его геометрические конструкции (точки, углы, и векторы) в терминах его собственной относительной системы координат. Например, дуги устанавливают систему координат, в которой 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;

}


Словарь Размещения


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



Словари


Чтобы создавать новый словарь, Вы должны создать образец 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");



Смешивание модели транзакции с открытым и близким механизмом


Операционная модель сосуществует с регулярным открытым и близким механизмом, описанным в главе 5, “ Объекты Базы данных. ” Однако, если Вы используете операционную модель, рекомендуется, чтобы Вы не смешали это с открытым и закрыли механизм. Например, если Вы получили указатель на объект, используя AcTransaction:: getObject (), Вы не должны вызвать близко () на объектном указателе, который мог вызывать неожиданных результатов и может разрушаться AutoCAD. Однако, Вы свободны открывать и закрыть специфический объект, даже если транзакции активны. Вы можете также инициализировать новые объекты, добавлять их к базе данных, и закрывать их, в то время как транзакции активны. Первичная цель наличия смешанной модели состоит в том, чтобы позволить одновременное выполнение множественных приложений, где некоторое управление транзакции использования и другие делают не, но все из них работают на тех же самых объектах.



События контекста ввода


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 <adslib.h>
#include <aced.h>
#include <dbmain.h>
#include <rxregsvc.h>
#include <acedinpt.h>
#include <acdocman.h>
// 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<AcGePoint3d>& points,
const resbuf* entMask);
void
endSSGet(
Acad::PromptStatus returnStatus,
const AcArray<AcDbObjectId>& 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<AcGePoint3d>& 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<AcDbObjectId>& 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);



Соединение Гиперсвязей с примитивами


ObjectARX позволяет Вам связывать гиперсвязи с примитивами, используя классы AcDbHyperlink, AcDbHyperlinkCollection, и AcDbEntityHyperlinkPE. Гиперсвязь может быть URL или адрес не-сети типа местного файла. Вы можете прикреплять, рассматривать, редактировать, и перечислять гиперсвязи в пределах вашего приложения.

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



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


Чтобы сохранять базу данных, используйте 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

()



Сохраненный Программным обеспечением Autodesk


Следующий AcDbDatabase метод возвращает Adesk:: kTrue, если это решает, что база данных была последняя сохранена программным обеспечением Autodesk (типа AutoCAD или AutoCAD LT®):

Adesk::Boolean

dwgFileWasSavedByAutodeskSoftware();



Сокрытие Диалоговых окон


Пользователь не может делать интерактивный выбор, в то время как диалоговое окно активно. Если Вы хотите, чтобы  пользователь делал выбор из графического экрана, Вы должны скрыть ваше диалоговое окно и затем восстанавливать это. Сокрытие поля - тот же самый как окончание этого с 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);



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


Поскольку ObjectDBX работает без AutoCAD, ваше приложение должно проявить внимание к элементам, которые программа ObjectARX не была бы должна адресовать. Эти элементы включают AcDbDatabase и использование разделов области просмотра, использование DWG файлов от более ранних выпусков, и имеющий дело с расширенными Данными Примитива (EED) и растровыми изображениями. Все эти темы и больше обсуждены в этой секции.



Создайте 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



Создание блок-ссылки с Атрибутами


Блок-ссылка - примитив это ссылки запись таблицы блоков. Это содержит точку вставки, ECS информация, X, Y, Z

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

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



Создание Дополнительных клавиш 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;

};

};