Уровень Примитива
Все примитивы имеют связанный уровень. База данных всегда содержит по крайней мере один уровень (уровень 0). Как с linetypes, Вы можете определить уровень для примитива. Если Вы не определяете уровень, заданное по умолчанию значение уровня базы данных используется для нового примитива.
Каждый уровень также связал свойства, которые включают замораживающийся / таял, вкл\выкл, блокируемый / разблокир, цвет, linetype, и область просмотра (см. главу 7, “ Контейнерные Объекты ”). Когда цвет примитива или linetype - BYLAYER, значение свойства уровня используется для примитива.
Если значение уровня определено для примитива, текущее значение уровня базы данных игнорируется.
Следующие функции дают возможность Вам установить уровень для примитива, или по имени или объектом ID:
Acad::ErrorStatus
AcDbEntity::setLayer(const char* newVal);
Acad::ErrorStatus
AcDbEntity::setLayer(AcDbObjectId newVal);
Эта функция возвращает название{*имя*} текущего уровня примитива:
char* AcDbEntity::layer() const;
Эта функция возвращает объект ID для текущего уровня (объект типа AcDbLayerTableRecord):
AcDbObjectId AcDbEntity::layerId() const;
Уровень проверок правильности
AcBr:: ValidationLevel перечисление устанавливает уровень проверки правильности для объекта AcBr. Если kFullValidation (по умолчанию после объектной реализации) определен, каждая функция, которая обращается к brep
топологии (непосредственно или косвенно) первые проверки связанный объект базы данных AutoCAD, чтобы видеть, изменилось ли это, так как объект AcBr был последний набор. Это - дорогая операция, но это гарантирует, что все brep данные - в пределах контекста. Если kNoValidation определен, база данных не проверена, если это не критическое к завершению задач функции. Это более эффективно, но не гарантирует, что brep данные - в пределах контекста. Установка уровня проверок правильности на основании " объект в объект " предотвращает любые столкновения между приложениями, загруженными одновременно.
Уровни Совместимости
Ваше ObjectARX-приложение может иметь один из четырех уровней совместимости с MDI:
§ SDI-ТОЛЬКО
§ MDI-ЗНАЮЩИЙ
§ MDI-СПОСОБНЫЙ
§ MDI-РАСШИРЕННЫЙ
SDI-ТОЛЬКО - минимальное требование, но MDI-СПОСОБНАЯ совместимость рекомендуется.
MDI поддерживает контекст выполнения в документ и обеспечивает средство для разрешения единственного контекста выполнения, чтобы быть активным при переключении документов.
Условная Фильтрация
Относительные операторы, только описанные - двоичные операторы. Вы можете также проверять группы, создавая вложенные выражения Boolean те операторы условного выражения использования. Условные операторы также определены -4 группами, но они должны быть соединены.
Следующий типовой код выбирает все круги в рисунке к радиусу 1.0 и всем линиям на уровне “ABC”.
eb1 = acutBuildList(-4, "<or",-4, "<and", RTDXF0,
"CIRCLE", 40, 1.0, -4, "and>", -4, "<and", RTDXF0,
"LINE", 8, "ABC", -4, "and>", -4, "or>", 0);
acedSSGet("X", NULL, NULL, &eb1, ssname1);
Условные операторы не чувствительны к регистру; Вы можете использовать эквиваленты нижнего регистра.
ОБРАТИТЕ ВНИМАНИЕ на выражения Conditional, которые проверяют на расширенные данные, использующие -3 группа, может содержать только -3 группы. См. “ Фильтрующий для Расширенных Данных ” на странице 206.
К выделите всё кругам, которые расширили{*продлили*} данные, зарегистрированные или на “APP1” или “APP2”, но не оба, Вы могли использовать следующий код.
eb1 = acutBuildList(-4, "<xor", -3, "APP1", -3, "APP2", -4, "xor>", 0);
acedSSGet("X", NULL, NULL, &eb1, ssname1);
Установка Черт Примитива
Имеются три уровня, от которых цвет примитива, уровень, и значения linetype может быть установлен: drawable уровень, уровень подпримитивов, и подпримитивный уровень. Другие черты могут сходим только один или два из уровней:
§
Drawable уровень. Выполнение setAttributes () определяет, что заданные по умолчанию черты для примитивов имели обыкновение отображать drawable. Для большинства примитивов, полный объект представлен, используя текущие свойства примитива: linetype, цвет, уровень, и так далее.
§ Subentity Level (Уровень Подпримитивов). Вы можете определить определенные черты, которые нужно использовать для определенных частей drawable в течение worldDraw () или viewportDraw () выполнение. Вы можете использовать интерфейс AcGiSubEntityTraits, чтобы перегрузить черты, которые были определены в setAttributes () запрос. Как только значение для черты установлено, это используется для всех последующих примитивов до конца метода или пока новое значение определено.
ОБРАТИТЕ ВНИМАНИЕ В этой главе, подпримитив термина используется по-другому чем в главе 6, “примитивах”, где термин относится к определенным геометрическим частям примитива. В этой главе, подпримитив - не часть примитива; это - только уровень, на котором значения черты могут быть установлены и изменен.
§ Subprimitive Level Функции примитива оболочки имеют необязательные параметры, которые позволяют Вам определять богатый набор черт на "в край" и основание "в лицо". (См. примеры кода в “Примитивах” на странице 696.) Для любой черты, этот механизм требует, чтобы Вы установили значения для всех граней или лиц, или для ни одного из них. Вы устанавливаете только черты, которые Вы хотите. Например, Вы можете устанавливать цвета граней оболочки или поймать в сети без того, чтобы иметь необходимость устанавливать уровни или linetypes, но Вы должны определить цвет для каждого края. В добавлении, чтобы поймать в сети и черты подпримитива оболочки, имеется версия текстовой примитивной функции, которая имеет текстовый параметр стиля. Текстовый стиль может быть установлен только при подпримитиве (примитив " в текст ") уровень. Подпримитивные значения черты заменяют значения соответствующего набора черт в уровнях drawable и подпримитиве.
Установка ObjectDBX Библиотек
ОБРАТИТЕ ВНИМАНИЕ, что следующее обсуждение принимает основное понимание технологии инсталлятора, определенно InstallShield 3.0 и 5.0.
AutoCAD ObjectDBX общедоступные библиотеки включает группу файлов, которые были разработаны с намерением что они использоваться множественными приложениями. Эта характеристика требует, чтобы они были помещены в общее местоположение, доступное для множественных приложений на автоматизированном рабочем месте пользователя. Autodesk выбрал рекомендуемое выполнение Microsoft установки файлов этого характера в каталоге Common Files. Так как возможно, что ваш инсталлятор может совместно использовать эти файлы с другими приложениями, Вы должны следовать некоторый простой, все же критический, руководящие принципы при установке файлов.
Установка Параметров для Перетащенной Последовательности
Прежде, чем Вы звоните, AcEdJig:: перетаскивают () функцию, Вы должны установить подсказку дисплея для перетащенной последовательности.
Подсказка дисплея - текст, показанный на командной строке в течение перетащенной последовательности. Используйте следующую функцию, чтобы установить подсказку дисплея:
void AcEdJig::setDispPrompt(const char* prompt);
Установка текущего документа без его активации
Имеются несколько особенностей, которые неявно работают на текущем документе, который может отличаться от активного документа. Вы можете использовать функцию AcApDocManager:: setCurDocument () с активизирующимся набором параметров к kFalse, чтобы делать текущий документ и активный отличный документ. Особенности, которых это является необходимым, включают:
Использование любых функций взаимодействия пользователя, типа acedXXX () функции.
Создание базы данных, которая будет связана со специфическим документом.
Получение или управление набором выборов без того, чтобы требовать взаимодействие пользователя.
функции Using, описанные в aced.h.
Когда активный и текущий документы различны, все функции ввода пользователя и члены относительно документа, типа графического экрана, будут заблокированы. Это включает функции для обоих приложений ObjectARX и ActiveX.
Всякий раз, когда Вы устанавливаете текущий документ без также формирования этого, setCurDocument () вызывающая программа должна восстановить текущий документ, чтобы быть тем же самый как активный документ когда закончено. Однако, если это не сделано к времени, что следующий входной случай обработан, текущий документ будет переключен назад к активному документу.
Установка Текущих Значений Базы данных
Если свойство данных типа цвета или linetype не определено для объекта, текущее значение базы данных, для которого данные используются. Следующие разделы выделяют функции, имел обыкновение определять текущие значения данных, связанные с базой данных.
Установка версии как SHAREDFILE
Весь DLLS Autodesk обеспечивает, содержат ресурс версии. При установке этих файлов Вы должны определить, что они, быть модифицировано только, если версия равна или большая чем те которые могут существовать на машине пользователя. InstallShield обеспечивает пару способов делать это использование комбинация ФЛАЖКОВ COMP_UPDATE_VERSION и COMP_UPDATE_SAME.
Кроме того Вы должны также отметить эти файлы с флажком SHAREDFILE при установке. Это будет гарантировать, что Вы поддерживаете подсчет ссылки к другим прикладным инсталляторам, которые могут устанавливать и использование этих библиотек и файлов.
Следующий сценарий InstallShield - пример, который устанавливает acge15.dll использование версия и общедоступный механизм файла.
TARGETDIR = COMMONFILES ^ "Autodesk Shared";
nReturn = XCopyFile (
"acge15.dll", "acge15.dll",
COMP_UPDATE_SAME |
COMP_UPDATE_VERSION |
SHAREDFILE);
if (nReturn < 0 ) then
// Report failure
endif;
Установка Заданного по умолчанию Формата файла
ObjectARX обеспечивает способность определить заданный по умолчанию формат файла для SAVEAS, SAVE и команд QSAVE. (Команда AUTOSAVE всегда сохраняет рисунки в формате чертежного файла AutoCAD 2000.)
Класс AcApDocument содержит перечисление, которое определяет формат, используемый при сохранении рисунка к файлу. Его значения показываются в следующей таблице:
Name | Usage (file extension) | ||
kR12_dxf | AutoCAD Release 12/LT2 DXF (*.dxf) | ||
kR13_dwg | AutoCAD Release 13/LT95 Drawing (*.dwg) | ||
kR13_dxf | AutoCAD Release 13/LT95 DXF (*.dxf) | ||
kR14_dwg | AutoCAD Release 14/LT97 Drawing (*.dwg) | ||
kR14_dxf | AutoCAD Release 14/LT97 DXF (*.dxf) | ||
kR15_dwg | AutoCAD 2000 Drawing (*.dwg) | ||
kR15_dxf | AutoCAD 2000 DXF (*.dxf) | ||
kR15_Template | AutoCAD 2000 Drawing Template File (*.dwt) | ||
kNative | Current DWG version is AutoCAD 2000 | ||
kUnknown | Invalid format |
AcApDocument:: formatForSave () функция возвращается, поток{*ток*} сохраняет{*экономит*} формат, используемый SAVEAS, СОХРАНЯЕТ{*ЭКОНОМИТ*}, и командами QSAVE:
AcApDocument:: SaveFormat
FormatForSave ();
Возвращенное значение может быть или сеанс-широкая настройка по умолчанию, или различная установка, которую пользователь выбрал для этого документа. Если это - перегрузка для этого документа, это не будет упорствовать{*сохраняться*} поперек сеансов.
AcApDocmanager:: setDefaultFormatForSave () функция использует одно из значений SaveFormat, чтобы заставить формат файла использовать при сохранении рисунка к SAVEAS, СОХРАНЯТЬ{*ЭКОНОМИТЬ*}, и командам QSAVE. Это устанавливает сеанс-широкое значение по умолчанию, которое пользователь может выбирать временно перегружать для индивидуального документа:
Acad:: ErrorStatus
SetDefaultFormatForSave (
AcApDocument:: формат
SaveFormat);
Эти функции только непосредственно сообщают относительно или устанавливают формат файла для интерактивных команд, введенных пользователем. Если Вы хотите, чтобы ваше приложение использовало поток{*ток*}, сохраняют{*экономят*} формат, каждый раз Вы желаете сохранить{*экономить*} базу данных, Вы будете сначала должны вызвать{*назвать*} formatForSave (), и затем использовать возвращенное значение SaveFormat, чтобы определить, которые функционируют, чтобы звонить. Например, если бы formatForSave () возвратил kR14_dxf, Вы вызвали бы{*назвали бы*} acdbDxfOutAsR14 () чтобы записать базу данных как Выпуск 14 DXF файл.
Убедитесь, что брали следующий во внимание:
§ Или Вы или ваш пользователь можете устанавливать постоянный сеанс-широкий заданный по умолчанию формат для, сохраняют{*экономят*}, который будет удостоен, все сохраняют{*экономят*} команды кроме, АВТОСОХРАНЯЮТ{*АВТОЭКОНОМЯТ*}.
§ Только пользователь может временно (не постоянно между сеансами) перегружают эту установку для специфического документа.
§ formatForSave () метод возвращает формат, в котором пользователь желает, чтобы индивидуальный документ был сохранен; это будет или сеанс-широкое значение по умолчанию или временная перегрузка, как соответствующий.
"В документе"
Любая структура данных, значение, или другой элемент, который должен инициализироваться и поддерживаться для каждого документа.
"В контексте "
Структура данных, которая должна инициализироваться и поддерживаться для каждого контекста выполнения, включая контексты выполнения документа и прикладной контекст выполнения. Командный процессор AutoCAD - пример реализации " в контекст ".
"В приложении"
Структура данных, которая должна существовать только однажды в приложение.
Ведущие Приложения
“ Host-приложение” является тем, который содержит main(), WinMain (), или dllMain () в своем коде, и обеспечивает ведущие услуги, в которых программа ObjectDBX или ObjectARX нуждается.
Имеются два типа ведущих приложений, которые могут воспользоваться преимуществом интерфейса ObjectDBX, обеспечивает. Один тип ведущего приложения - AutoCAD 2000, с или без связанных ObjectARX-приложений. Второй тип – host-приложение не-AutoCAD’a, - не может загружать ObjectARX-приложение, и может только воспользоваться преимуществом определенных интерфейсов, обеспеченных DLL, содержащимся в ObjectDBX.
Вещественные числа
Реальные значения в AutoCAD - всегда с двойной точностью с плавающей точкой значения.
ObjectARX сохраняет этот стандарт, определяя специальный тип ads_real, следующим образом:
typedef double ads_real;
Реальные значения в ObjectARX-приложении имеют тип ads_real.
Входные Опции для Функций Ввода пользователя
Следующая таблица суммирует служебные биты, которые могут быть определены val параметром. Чтобы устанавливать больше чем одно условие одновременно, добавьте значения вместе, чтобы создать значение val между 0 и 127. Если val установлен на нуль, ни один из условий контроля не обращается к следующему запросу функции ввода пользователя.
ОБРАТИТЕ ВНИМАНИЕ На будущие версии AutoCAD, или ObjectARX может определять дополнительный acedInitGet () служебные биты, так что Вы должны избежать устанавливать любые биты, что не показывается в таблице или описано в этой секции.
Входные опции, установленные acedInitGet ()
Код | Бит | Описание Значения | |||
RSG_NONULL | 1 | Отвергают нулевой{*пустой*} ввод | |||
RSG_NOZERO | 2 | Отвергают нулевые значения | |||
RSG_NONEG | 4 | Отвергают отрицательные значения | |||
RSG_NOLIM | 8 | Не проверяют пределы рисунка, даже если LIMCHECK включен | |||
RSG_DASH | 32 | Пунктирные линии Использования при рисунке резиновой полосы выравнивают или поле | |||
RSG_2D | 64 | Игнорируют координату Z трехмерных точек (acedGetDist () только) | |||
RSG_OTHER | 128 | Позволяют произвольный ввод — вводит ли пользователь |
Следующая выборка программы показывает использование acedInitGet() чтобы основать запрос к acedGetInt () функция.
int age;
acedInitGet(RSG_NONULL | RSG_NOZERO | RSG_NONEG, NULL);
acedGetInt("How old are you? ", &age);
Эта последовательность спрашивает возраст пользователя. AutoCAD автоматически отображает сообщение об ошибках и повторяет подсказку, если пользователь пробует вводить отрицательное или нулевое значение, нажмите ENTER только, или введите ключевое слово. (Сам AutoCAD отклоняет попытки ввести значение, которое - не целое число.)
Опция RSG_OTHER позволяет следующему запросу функции ввода пользователя принять произвольный ввод. Если RSG_OTHER установлен, и пользователь вводит непризнанное значение, acedGetxxx () функциональные возвращения RTKWORD, и ввод могут быть восстановлены{*отысканы*} запросом к acedGetInput (). Поскольку конечный пользователь пространств{*пробелов*} вводит также, как ВВОДЯТ, делает, произвольный ввод никогда не содержит пространство{*пробел*}. Опция RSG_OTHER имеет самый низкий приоритет всех опций, перечисленных в предшествующей таблице; если acedInitGet () запрос отверг отрицательные числа{*номера*} с RSG_NONEG, например, AutoCAD все еще отклоняет их.
Следующий код позволяет произвольный ввод (проверка ошибок минимальна).
int age, rc;
char userstring[511];
acedInitGet(RSG_NONULL | RSG_NOZERO | RSG_NONEG | RSG_OTHER, "Mine Yours");
if ((rc = acedGetInt("How old are you? ", &age)) == RTKWORD) {
// Keyword or arbitrary input
acedGetInput(userstring);
}
В этом примере, acedGetInt () возвращает значения, показанные в следующей таблице, в зависимости от ввода пользователя.
Произвольный ввод пользователя
Ввода пользователя |
Результат |
41 |
AcedGetInt () возвращает RTNORM и устанавливает возраст в 41 |
m |
AcedGetInt () возвращает RTKWORD, и acedGetInput () возвращает “Источник” |
y |
AcedGetInt () возвращает RTKWORD, и acedGetInput () “Ваши” возвращения |
Двадцать |
AcedGetInt () возвращает RTKWORD, и acedGetInput () возвращается “двадцать” |
Какой??? |
AcedGetInt () возвращает RTKWORD, и acedGetInput () возвращения “ какой??? ” |
-10 |
AutoCAD отклоняет этот ввод и восстанавливает изображение подсказки, поскольку RSG_NONEG установлен (другие разрядные коды имеют приоритет по RSG_OTHER) |
-34.5 |
AcedGetInt () возвращает RTKWORD, и acedGetInput () возвращается ", “-34.5" AutoCAD не отклоняет это значение, потому что это ожидает целое число, не реальное значение (если бы бы это было acedGetReal () запрос, AutoCAD принял бы отрицательное целое число как произвольный ввод, но отклонил бы отрицательное реальное значение) |
Видимость
AcGiEdgeData и классы AcGiFaceData позволяют Вам определять тип видимости для граней или лиц в примитиве оболочки или сети. Должен иметься точно один вход видимости в массиве для каждого края или лица в примитиве.
Прохождение в массиве неправильного размера вызывает непредсказуемых результатов.
Тип видимости для граней и лиц, AcGiVisibility, может иметь одно из следующих значений:
§ kAcGiInvisible
§ kAcGiVisible
§ kAcGiSilhouette
Если поверхность не изогнута, или край не требован для рассмотрения целей, определять kAcGiInvisible. Для жестких граней поверхностных или видимых складок, определите kAcGiVisible. Для граней или лиц, которые Вы можете видеть от некоторых точек зрения, определите kAcGiSilhouette. Тип видимости силуэта признан только командой HIDE; иначе, это интерпретируется как kAcGiVisible.
Например, в твердом цилиндре, показанном ниже, грани, которые формируются, оправы цилиндра - видимые грани. Грани latitudinal - невидимые грани, так как они никогда не используются для рассмотрения целей. Продольные грани - грани силуэта, так как они используются, когда цилиндр рассматривается от некоторых углов.
Видимость Примитива
Если Вы определяете, что примитив невидим, это будет невидимо независимо от других параметров настройки в базе данных. Другие коэффициенты{*факторы*} могут также заставлять примитив быть невидимыми.
Например, примитив не будет отображен, если его уровень выключен или закрепляется.
Значение AcDb:: Видимость может быть или kInvisible или kVisible.
Acad::ErrorStatus
AcDbEntity::setVisibility(AcDb::Visibility newVal);
AcDb::Visibility
AcDbEntity::visibility() const;
ViewAcDb
ViewAcDb - Многодокументная среда средство просмотра чертежного файла (MDI), которое использует SimpleView и WhipView для отображения видов DWG файлов.
ViewAcDb - по существу испытание, используют для AcDb.dll, AcGix.dll, и выполнение представления{*вида*}.
ViewportDraw () Функция
Если drawable возвращает ложь от worldDraw () повторный вызов, это вызывает viewportDraw () однажды для каждой активной области просмотра, чтобы позволить drawable описывать его область просмотра-определенный дисплей. AcGiViewportDraw и AcGiViewportGeometry близко связаны с worldDraw () эквиваленты, потому что они происходят от тех же самых базовых классов.
ViewportDraw () функция работает подобным способом как worldDraw (). AcDbEntity:: viewportDraw () функция берет указатель на объект AcGiViewportDraw и формирует представление-определенное представление примитива. Область просмотра рисует объект, также обеспечивает доступ к другим объектам, которые включают следующее:
§ AcGiViewportGeometry
§ AcGiSubEntityTraits
§ AcGiViewport
Объект геометрии области просмотра обеспечивает тот же самый список примитивов как мировой объект геометрии и добавляет к этому следующие примитивы, которые используют глаз и координаты пространства дисплея, чтобы рисовать ломаные линии и многоугольники:
§ polylineEye ()
§ polygonEye ()
§ polylineDc ()
§ polygonDc ()
Объект черт подпримитива области просмотра - тот же самый, поскольку используемое миром рисует объект (AcGiSubEntityTraits). Объект области просмотра обеспечивает функции для запроса матриц преобразования области просмотра и рассмотрения параметров.
ПРЕДУПРЕЖДЕНИЕ! Указатель на объект AcGi типа AcGiWorldDraw или AcGiViewportDraw не должен быть сохранен как глобальная или статическая переменная. Не сохраните копии указателей на объекты AcGi поперек, вызывает к worldDraw () и viewportDraw (). Однажды это возвращение функций, указатели больше не имеют силу.
Вложение Диалоговых окон
Вы создаете и управляете вложенными диалоговыми окнами просто, вызывая ads_new_dialog () и ads_start_dialog () изнутри функции повторного вызова.
Пользователь должен выйти из вложенного диалогового окна перед использованием предыдущего диалогового окна снова.
AutoCAD налагает предел не больше, чем восемь вложенных диалоговых окон, но Вы не должны вложить диалоговые окна глубже чем три или четыре.
Хотя ads_term_dialog () заканчивает все диалоговые окна сразу, это не возвращает код состояния, так не имеется никакого пути для вашего приложения, чтобы различить между сокрытием вложенного поля и отмены полей из-за условия ошибки.
Вложение транзакций
Транзакции могут быть вложены — то есть Вы можете запустить одну транзакцию внутри другой и заканчивать или прерывать недавнюю транзакцию. Операционный менеджер поддерживает транзакции в стеке, с самой современной транзакцией наверху стека. Когда Вы запускаете новую транзакцию, используя AcTransactionManager:: startTransaction (), новая транзакция добавлена к вершине стека, и указатель на это возвращен (образец AcTransaction). Когда кто - то вызывает AcTransactionManager:: endTransaction () или AcTransactionManager:: abortTransaction (), транзакция наверху стека закончена или прервана.
Когда объектные указатели получены от объекта IDs, они всегда связываются с самой современной транзакцией. Вы можете получить недавнюю транзакцию, используя AcTransactionManager:: topTransaction (), затем использовать AcTransaction:: getObject () или AcTransactionManager:: getObject () чтобы получить указатель на объект. Операционный менеджер автоматически связывает объектные указатели, полученные с недавней транзакцией. Вы можете использовать AcTransaction:: getObject () только с самой современной транзакцией.
Когда вложенные транзакции начаты, объектные указатели, полученные во внешних содержащих транзакциях также доступны для операции в самой внутренней транзакции. Если недавняя транзакция прервана, все операции, сделанные на всех объектах (связанный или с этой транзакцией или содержащими) так как начало недавней транзакции отменено, и объекты прокручены назад к состоянию в начале недавней транзакции.
Объектные указатели, полученные в недавней транзакции прекращают иметь силу, как только это прервано.
Если самая внутренняя транзакция закончена успешно, вызывая AcTransactionManager:: endTransaction (), объекты, чей указатели были получены в этой транзакции, станут связанным с содержащей транзакцией и доступен для операции. Этот процесс продолжен, пока наиболее удаленная (первая) транзакция не закончена, в котором модификации времени на всех объектах совершены{*переданы*}. Если наиболее удаленная транзакция прервана, все операции на всех объектах отменены, и ничто не совершено{*передано*}.
Внешние Функции
Как только ObjectARX-приложение определило его внешние функции (вызыв acedDefun ()), функции могут быть вызваны пользователем AutoLISP и программами AutoLISP и функциями, как будто они были встроенные или определяемые пользователем функции AutoLISP. Внешняя функция может быть, пропускал значения AutoLISP и переменные, и может возвращать значение выражению AutoLISP, которое вызывает это.
Некоторые ограничения применяются и описаны в этой секции.
Внешние ссылки
Внешние ссылки (таблицы перекрестных ссылок) могут быть созданы и управляться через несколько глобальных функций. Эти глобальные функции подражают возможностям команды XREF AutoCAD. Функции, обеспеченные
acedXrefAttach ()
acedXrefOverlay ()
acedXrefUnload ()
acedXrefDetach ()
acedXrefReload ()
acedXrefBind ()
acedXrefXBind ()
acedXrefCreateBlockname ()
acedXrefReload ()
Для информации относительно команды XREF AutoCAD, см. Руководство программиста AutoCAD.
Главное, программирующее соображение{*рассмотрение*} относительно таблиц перекрестных ссылок - то, что, для каждой таблицы перекрестных ссылок, который приложен к рисунку, отдельная база данных создана, чтобы представить рисунок, содержащий таблицу перекрестных ссылок. Блочный отчет{*запись*} таблицы в основном рисунок содержит название{*имя*} внешнего рисунка и указывать на объекты образцового пространства{*пробела*} внешне упомянутого рисунка. База данных таблицы перекрестных ссылок также содержит другие блочные отчеты{*записи*} таблицы и входы таблицы идентификаторов, требуемые, чтобы решить все ссылки{*справочники*} от основного блочного отчета{*записи*} таблицы (уровни, linetypes, и так далее).
Вы можете создавать редактора реактор, как описано в главе 15, “Уведомлении”, контролировать события таблицы перекрестных ссылок. AcEditorReactor класс обеспечивает следующие реакторные функции повторного вызова:
beginAttach ()
otherAttach ()
abortAttach ()
endAttach ()
redirected ()
comandeered ()
При использовании этих функций, будьте внимательным, чтобы обратить внимание, которая база данных возвращается. Также, знайте, что рисунок таблицы перекрестных ссылок может самостоятельно содержать таблицы перекрестных ссылок к дополнительным рисункам. Для получения дополнительной информации на AcEditorReactor классе, см. ObjectARX Ссылку{*справочники*}.
Объекты Таблицы перекрестных ссылок в рисунке могут изменяться, но они не могут быть сохранены к первоначальному рисунку таблицы перекрестных ссылок (рисунок оригинала только для чтения).
Внешняя ссылка Пред- и Последующая обработка
Внешняя ссылка (таблица перекрестных ссылок) пред- и последующая обработка делает возможным восстановить приложенную таблицу перекрестных ссылок в оперативной памяти AcDbDatabase так, чтобы это могло быть сохранено назад к файлу. В течение решения таблицы перекрестных ссылок, много отчетов{*записей*} таблицы идентификаторов искарежены, и некоторые стерты. Исторически, это было сделано, чтобы упростить процесс решения, и было приемлемо, потому что базы данных были только для чтения. Эта обработка делает возможным временно полностью изменить изменения{*замены*} решения так, чтобы база данных таблицы перекрестных ссылок могла изменяться и написан назад к ее файлу.
Функции, которые помогают в пред- и последующая обработка, добавлены к AcDbDatabase. Они включают сервисную функцию, чтобы найти связанный блочный отчет{*запись*} таблицы от базы данных таблицы перекрестных ссылок, также как способности восстановить решенную таблицу перекрестных ссылок, и сбрасывать это назад к надлежащему решенному условию{*состоянию*} после восстановления.
Общепринятое использование для этих функций было бы должно делать восстановление к первоначальным символам, делать модификации к базе данных, сохранять{*экономить*} базу данных, и затем восстанавливать отправленные{*ускоренные*} символы. Эти шаги должны быть написаны в одиночный блок кода, предотвращать попытки восстановить рисунок главного компьютера, выполнять любые команды таблицы перекрестных ссылок, или обеспечивать подсказки пользователя, в то время как база данных таблицы перекрестных ссылок находится в ее восстановленном условии{*состоянии*}.
Функции
AcDbDatabase:: xrefBlockId ()
AcDbDatabase::restoreOriginalXrefSymbols()
AcDbDatabase::restoreForwardingXrefSymbols()
Восстановление состояния
Если Вы определили kFalse для автоотмены, applyPartialUndo объекта () функция называется, когда команда UNDO вызвана. ApplyPartialUndo () функция - виртуальная функция на AcDbObject.
Полученные классы могут осуществлять эту функцию, чтобы интерпретировать класс - определенную информацию, сохраненную регистратором отмены и читать это в. ApplyPartialUndo () функция должна гарантировать, что ваш класс выполнил модификацию. Если не, это супер-сообщение, как показано в следующем примере.
Если Вы осуществляете частичный механизм отмены, убедитесь, что вызвали{*назвали*} следующую функцию так, чтобы никакая регистрация не случилась по умолчанию.
AssertWriteEnabled (kFalse, kFalse);
Как пример, имеется AsdkPoly-функция applyPartialUndo()
Acad::ErrorStatus
AsdkPoly::applyPartialUndo(AcDbDwgFiler* filer,
AcRxClass* classObj)
{
// The first thing to check is whether the class matches
// ours. If it doesn’t, we call the base class’s
// applyPartialUndo(); hopefully, one of them will
// take care of it.
//
if (classObj != AsdkPoly::desc())
return AcDbCurve::applyPartialUndo(filer, classObj);
// Read the op-code and call the appropriate "set"
// method to undo what was done. The "set" does the
// filing again for redo.
//
Adesk::Int16 shortCode;
filer->readItem(&shortCode);
PolyOpCodeForPartialUndo code;
code = (PolyOpCodeForPartialUndo)shortCode;
Adesk::UInt32 value32;
switch (code) {
case kSetNumSides:
filer->readItem(&value32);
AOK(setNumSides(value32));
break;
default:
assert(Adesk::kFalse);
break;
}
return Acad::eOk;
}
Возвращаемые значения против результатов функций
Несколько ObjectARX глобальные функции имеют пустой тип возвращения, и некоторые непосредственно возвращают их результатов, но больше всего имеют int, напечатают и возвращают целочисленный код состояния, который указывает, потерпел ли функциональный запрос, за которым следуют или неудачу.
Код RTNORM указывает, что функция преуспела; другие коды указывают неудачу или специальные условия. Библиотечные функции, которые возвращают код состояния, передают их фактических результатов (если любой) поддерживает к вызывающей программе через параметр, который пропускает ссылка.
ПРИМЕЧАНИЕ Не путает параметры результата библиотечной функции и значения с его возвращаемым значением. Функция возвращает целочисленный код состояния. Это размещает его результатов в параметры, прошел (ссылкой) назад к функции, которая вызывает это.
Рассмотрите следующие смоделированные объявления для нескольких типичных функций ObjectARX:
int acdbEntNext(ads_name ent, ads_name result);
int acedOsnap(ads_point pt, char *mode, ads_point result);
int acedGetInt(char *prompt, int *result);
Приложение могло вызывать эти функции со следующими инструкциями C++:
stat = acdbEntNext(ent, entres);
stat = acedOsnap(pt, mode, ptres);
stat = acedGetInt(prompt, &intres);
После того, как каждая функция вызвана, значение stat переменной указывает или успех (stat == RTNORM) или неудачу (stat == RTERROR или другой код ошибки, типа RTCAN для отмены). Последний параметр в каждом списке - параметр результата, который нужно пропустить ссылкой. Если успешно, acdbEntNext() возвращает имя примитива в его entres параметре, acedOsnap() возвращает точку в ptres, и acedGetInt() возвращается, целое число приводит к intres. (Типы ads_name и ads_point - типы массива, который является, почему entres и ptres параметры явно не появляются как указатели.)
ОБРАТИТЕ ВНИМАНИЕ В ObjectARX глобальных функциональных объявлениях параметры результата всегда следуют за параметрами, которые передают входные значения к функции.
Возвращение Значений к Функциям AutoLISP
ObjectARX обеспечивает набор функций, который позволяет возвращать значения в AutoLISP. Эти функции возвращения значения не имеют никаких копий AutoLISP. Следующая таблица суммирует эти функции.
Имя функции |
Результат | ||
AcedRetInt |
Целочисленное значение | ||
AcedRetReal |
Реальное значение | ||
AcedRetPoint |
Трехмерная точка | ||
AcedRetStr |
Строка | ||
AcedRetVal |
Значение пропускало “generically” в буфере результатов | ||
AcedRetName |
Примитив (RTENAME) или выбор устанавливает имя (RTPICKS) (см. главу 3 для подробной информации относительно наборов выбора и примитивов) | ||
AcedRetT |
AutoLISP оценивает t (истину) | ||
AcedRetNil |
AutoLISP оценивает ноль | ||
AcedRetVoid |
Пустое значение: AutoCAD не отображает результат | ||
AcedRetList |
Список буферов результатов, возвращенных AutoLISP |
Следующий пример показывает схему вызванной функции, когда приложение получает запрос kInvkSubrMsg. Это возвращает реальное значение AutoLISP.
Int dofun
()
{
Ads_real x
// Проверить{*отметить*} параметры, и ввести условия здесь.
// Вычислить значение x.
AcedRetReal (x);
return GOOD;
}
ОБРАТИТЕ ВНИМАНИЕ, что внешняя функция может делать больше чем один запрос к функциям возвращения значения по единственному запросу kInvkSubrMsg, но функция AutoLISP возвращает только значение последней вызванной функцией.
Всегда имейте текущую базу данных
Хотя ObjectDBX позволяет Вам создавать много образцов AcDbDatabase, только можно быть текущая база данных. AcDb поддерживает внутренний глобальный указатель на эту текущую базу данных, и AcDbHostApplicationServices метод workingDatabase () возвращает копию этого внутреннего указателя. Всякий раз, когда AcDbDatabase:: readDwgFile () метод используется, внутренний текущий указатель базы данных сброшен, чтобы указать на ту базу данных. Когда база данных, которая является текущей, удалена, внутренний текущий указатель базы данных установлен в NULL.
Это означает, что в ситуациях, где ваш код читает, множественные базы данных и возможно удаляют некоторых из них по пути, Вы должны убедиться, что Вы используете AcDbHostApplicationServices::setWorkingDatabase() метод в соответствующих местах, чтобы установить внутренний текущий указатель базы данных на надлежащую текущую базу данных.
Например, следующий код читает в одной базе данных, указанной pDbFirst (вызовите эту базу данных “сначала”). Это заставляет внутренний текущий указатель базы данных быть установленным в базу данных “ сначала. ” Код тогда читает в другой базе данных, указанной pDbSecond (вызовите эту базу данных “вторая”), который теперь заставляет внутренний текущий указатель базы данных быть установленным в базу данных “вторая”. Код затем вставляет базу данных “вторая” в базу данных “сначала” и удаляет базу данных “вторая”. Когда база данных “секунда” удалена, внутренний текущий указатель базы данных указывает на это, так что внутренний указатель установлен в NULL. Это означает, что после того, как стирание базы данных, AcDb имеет указатель текущего рисунка NULL. Это ведет к фатальным ошибкам, если любой код, к которому к ссылкам внутренний текущий указатель базы данных обращаются.
Чтобы предотвращать это, после стирания базы данных “вторая” в коде вашего приложения, код должен назвать ведущей setWorkingDatabase() методом, проходящим в указателе на базу данных “сначала”, чтобы восстановить базу данных “сначала” как текущая база данных для ObjectDBX, следующим образом:
// Делать "сначала" текущую базу данных.
AcDbDatabase *pDbFirst = new AcDbDatabase(Adesk::kFalse);
pDbFirst->readDwgFile("first.dwg");
// Теперь заставите "секунду" быть текущая база данных.
AcDbDatabase *pDbSecond = new AcDbDatabase(Adesk::kFalse);
pDbSecond->readDwgFile("second.dwg");
// Вставить "секунду" в "первый" как ABLOCK.
Acad::ErrorStatus es;
AcDbObjectId blockId;
es = pDbFirst->insert(blockId, "ABLOCK", pDbSecond);
// Удаление "секунды" делает текущую базу данных NULL.
delete
pDbSecond;
// Делать текущую базу данных "сначала" снова.
myHostServices->setWorkingDatabase(pDbFirst);
Удалите все AcDbDatabases
при выходе из приложения
Всегда удалите все базы данных перед переходом к вашему приложению. Кроме порождения утечки памяти в вашем приложении, отказ удалять все базы данных может приводить к фатальной ошибке на закрытии. Пожалуйста также см. следующую секцию, “ AcDbDatabase::insert(), ” относительно специальных соображений разрушения для вставленных баз данных.
Всегда Инициализируйте AcDbDatabase
Вы должны всегда инициализировать по крайней мере один объект AcDbDatabase перед использованием любого кода AcDb. Это - то, потому что создание полного AcDbDatabase инициализирует набор глобальных переменных, которых некоторые библиотечные элементы требуют. (См. setWorkingDatabase () метод AcDbHostApplicationServices класса в ObjectARX Ссылке для подробностей.) Когда AutoCAD присутствует, имеется всегда “текущий рисунок” AcDbDatabase, что ObjectARX
полагается, чтобы удовлетворить все эти требования. Приложение ObjectDBX должно подражать этому поведению.
Если Вы намереваетесь записать непосредственно к вашей базе данных, Вы должны инициализировать это, используя конструктор AcDbDatabase с Adesk:: kTrue параметр. Эта версия конструктора создает жизнеспособный пустой рисунок, готовый к модификации и формирует таблицы базы данных и инициализирует их к значениям по умолчанию. Следующее - пример инициализирования базы данных:
AcDbDatabase *pDb = new AcDbDatabase(Adesk::kTrue);
Если Вы намереваетесь читать чертежный файл в базу данных, используйте конструктор AcDbDatabase с Adesk:: kFalse параметр, немедленно сопровождаемый запросом к readDwgFile () функция. Эта версия конструктора создает полностью пустую базу данных, которая полагается на последующий запрос к readDwgFile () чтобы заполнить его внутренние структуры данных. При использовании они в комбинации улучшают эффективность при чтении DWG файла по использованию другой формы конструктора, потому что таблицы и глобальные переменные должны только быть инициализированными однажды readDwgFile (). Имеется пример чтения рисунка в предварительно инициализированную базу данных:
AcDbDatabase *pDb = new AcDbDatabase(Adesk::kFalse);
pDb->readDwgFile(filename);
Множитель вызывает к readDwgFile () на той же самой базе данных, не поддержаны.
И в ObjectARX и ObjectDBX, вызывая readDwgFile () после использования Adesk:: kTrue форма конструктора некоторый, чтобы вызвать отказ{*неудачу*}, если версия DWG
файла, который Вы читаете - Выпуск 12 или ранее. Это из-за несогласованности в пути, которым рисунки загружены до Выпуска AutoCAD 13.
Поскольку Вы не можете предсказывать, которые рисунки ваши конечные пользователи откроются, не закодируйте следующее:
// Не Делать этого.
AcDbDatabase *pDb = new AcDbDatabase(Adesk::kTrue);
pDb->readDwgFile(filename);
В течение развития, разработчики приложения
В течение развития, разработчики приложения ObjectDBX должны часто проверять законность их выполнения, открывая чертежные файлы, сохраненные их приложением в AutoCAD 2000. Это также поможет Вам в определении как к лучшему набору ваша область просмотра пространства модели.
Вставка Базы данных
AcDbDatabase:: вставка () функции копируют одну базу данных в базу данных, на которую функция элемента вызвана. AutoCAD объединяет объекты, которые это определяет, типа MLINE стиля и словарей ГРУПП; однако, это не заботится о копировании определенных приложением объектов, чей монопольное использование внедрено в названном объектном словаре. Вы должны передать{*переместить*} данные прикладной программы от исходной базы данных до целевой базы данных, используя AcEditorReactor функции уведомления.
ОБРАТИТЕ ВНИМАНИЕ На INSERT() функции исполняют глубоко имитацию, как описано в главе 18, при Глубоко Имитации. ”
Если конфликты возникают, когда исходные и целевые базы данных объединяются (например, если обе базы данных имеют то же самое название{*имя*} linetype), AutoCAD использует версию в целевой базе данных.
Следующая функция эквивалентна стандарту, тянущему{*рисующему*} команду INSERT:
Acad:: ErrorStatus
AcDbDatabase::insert(AcDbObjectId& BlockId,
const char* pBlockName,
AcDbDatabase* pDb);
Эта функция копирует объекты с образцового пространства{*пробела*} входной базы данных (pDb) в
указанный блочный отчет{*запись*} таблицы (pBlockName) и
возвращает блок ID нового блочного отчета{*записи*} таблицы (blockId). Приложение должно тогда создать ссылку{*справочники*} к блочной таблице, делают запись и прибавляют это к базе данных.
Следующая функция эквивалентна команде AutoCAD:
Acad:: ErrorStatus
AcDbDatabase::insert (const AcGeMatrix3d& Xform,
AcDbDatabase* pDb);
Эта функция копирует объекты с образцового пространства{*пробела*} входной базы данных (pDb) и помещает их в текущее пространство{*пробел*} новой базы данных (бумажное пространственное или образцовое пространство{*пробел*}), применяя указанное преобразование (xform) к объектам.
Вставлять блок с атрибутами в рисунок
1 Создают примитив блок-ссылки (AcDbBlockReference).
2 Называют setBlockTableRecord () функцией, чтобы определить объект ID упомянутой записи таблицы блоков. (Объект ID может также быть определен непосредственно в конструкторе блок-ссылки.)
3 Добавляют в конец блок-ссылку к записи таблицы блоков (пространство модели, пространство листа, или некоторый другой блок).
4 Используют запись таблицы блоков iterator на упомянутой записи таблицы блоков, ища определения атрибута. Для каждого найденного, создайте новый AcDbAttribute примитив, заполните это с данными определения атрибута, и затем добавьте в конец это к блок-ссылке, используя appendAttribute () функция.
Следующий пример создает блок-ссылку, заполняет атрибуты, и добавляет ссылку к базе данных. Это использует глобальные функции, чтобы получить ввод пользователя. CreateBlockWithAttributes () функция, показанная в предыдущем разделе используется, чтобы создать блок-ссылку. Этот пример использует запись таблицы блоков iterator, чтобы шагнуть через определения атрибута и создавать соответствующий атрибут для каждого определения атрибута. Атрибуты со значением установлены от первоначального определения атрибута, используя setPropertiesFrom () функция.
void
addBlockWithAttributes()
{
// Get an insertion point for the block reference,
// definition, and attribute definition.
//
AcGePoint3d basePoint;
if (acedGetPoint(NULL, "\nEnter insertion point: ",
asDblArray(basePoint)) != RTNORM)
return;
// Get the rotation angle for the attribute definition.
//
double textAngle;
if (acedGetAngle(asDblArray(basePoint),
"\nEnter rotation angle: ", &textAngle) != RTNORM)
return;
// Define the height used for the attribute definition text.
//
double textHeight;
if (acedGetDist(asDblArray(basePoint),
"\nEnter text height: ", &textHeight) != RTNORM)
return;
// Build the block definition to be inserted.
//
AcDbObjectId blockId;
defineBlockWithAttributes(blockId, basePoint,
textHeight, textAngle);
// Step 1: Allocate a block reference object.
//
AcDbBlockReference *pBlkRef = new AcDbBlockReference;
// Step 2: Set up the block reference to the newly
// created block definition.
//
pBlkRef->setBlockTableRecord(blockId);
// Give it the current UCS normal.
//
struct resbuf to, from;
from.restype = RTSHORT;
from.resval.rint = 1; // UCS
to.restype = RTSHORT;
to.resval.rint = 0; // WCS
AcGeVector3d normal(0.0, 0.0, 1.0);
acedTrans(&(normal.x), &from, &to, Adesk::kTrue,
&(normal.x));
// Set the insertion point for the block reference.
//
pBlkRef->setPosition(basePoint);
// Indicate the LCS 0.0 angle, not necessarily the UCS 0.0 angle.
//
pBlkRef->setRotation(0.0);
pBlkRef->setNormal(normal);
// Step 3: Open the current database’s model space
// block Table Record.
//
AcDbBlockTable *pBlockTable;
acdbHostApplicationServices()->workingDatabase()
->getSymbolTable(pBlockTable, AcDb::kForRead);
AcDbBlockTableRecord *pBlockTableRecord;
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord,
AcDb::kForWrite);
pBlockTable->close();
// Append the block reference to the model space
// block Table Record.
//
AcDbObjectId newEntId;
pBlockTableRecord->appendAcDbEntity(newEntId, pBlkRef);
pBlockTableRecord->close();
// Step 4: Open the block definition for read.
//
AcDbBlockTableRecord *pBlockDef;
acdbOpenObject(pBlockDef, blockId, AcDb::kForRead);
// Set up a block table record iterator to iterate
// over the attribute definitions.
//
AcDbBlockTableRecordIterator *pIterator;
pBlockDef->newIterator(pIterator);
AcDbEntity *pEnt;
AcDbAttributeDefinition *pAttdef;
for (pIterator->start(); !pIterator->done(); pIterator->step())
{
// Get the next entity.
//
pIterator->getEntity(pEnt, AcDb::kForRead);
// Make sure the entity is an attribute definition
// and not a constant.
//
pAttdef = AcDbAttributeDefinition::cast(pEnt);
if (pAttdef != NULL && !pAttdef->isConstant()) {
// We have a non-constant attribute definition,
// so build an attribute entity.
//
AcDbAttribute *pAtt = new AcDbAttribute();
pAtt->setPropertiesFrom(pAttdef);
pAtt->setInvisible(pAttdef->isInvisible());
// Translate the attribute by block reference.
// To be really correct, the entire block
// reference transform should be applied here.
//
basePoint = pAttdef->position();
basePoint += pBlkRef->position().asVector();
pAtt->setPosition(basePoint);
pAtt->setHeight(pAttdef->height());
pAtt->setRotation(pAttdef->rotation());
pAtt->setTag("Tag");
pAtt->setFieldLength(25);
char *pStr = pAttdef->tag();
pAtt->setTag(pStr);
free(pStr);
pAtt->setFieldLength(pAttdef->fieldLength());
// The database column value should be displayed.
// INSERT prompts for this.
//
pAtt->setTextString("Assigned Attribute Value");
AcDbObjectId attId;
pBlkRef->appendAttribute(attId, pAtt);
pAtt->close();
}
pEnt->close(); // use pEnt... pAttdef might be NULL
}
delete pIterator;
pBlockDef->close();
pBlkRef->close();
}
Встроенная MFC Поддержка Интерфейса пользователя
ObjectARX
имеет набор MFC Интерфейса пользователя (UI) связанные классы, которые легко позволяют Вам обеспечивать непротиворечивый UI. Это означает, что ваш UI может вести себя и иметь появление{*вид*} AutoCAD UI. Строго рекомендует использовать эти классы, так как они позволяют вашему приложению быть более сильно интегрированными с AutoCAD UI. Autodesk MFC система разделен на две библиотеки. Первый вызван{*назван*} AdUi и не Определенный автохамом. Второй вызван{*назван*} AcUi и содержит Определенное автохамом появление{*вид*} и поведение.
AdUi - MFC
динамически компонуемая библиотека расширения{*продления*}, имел обыкновение расширять{*продлевать*} некоторых из UI-имеющихся отношение классов MFC. Библиотека была разработана для использования с AutoCAD и другими изделиями{*программами*} Autodesk и содержит основные функциональные возможности. Библиотека компаньонов, AcUi, формирует на AdUi
структуру и обеспечивает AutoCAD- определенное появление{*вид*} и поведение. AdUi и AcUi библиотеки обеспечивают классы, которые расширяют{*продлевают*} обеспеченный MFC способами, которые позволяют ARX
разработчикам использовать те же самые UI функциональные возможности, найденные в AutoCAD. MFC разработчики может без швов использовать эти классы. Перечислены ниже основные области добавленных функциональных возможностей, обеспеченных AdUi и AcUi.
Чтобы использовать AdUi в приложении MFC-based, исходные файлы C++ проекта должны включить adui.h, и проект должен связать adui15.lib (adui15.dll
библиотека импорта).
Чтобы использовать AcUi в MFC-ОСНОВАННОМ приложении AutoCAD, исходные файлы C++ проекта должны включить adui.h, тогда acui.h, и проект должен связать acui15.lib
и adui15.lib. AutoCAD вызывает подпрограмму инициализации библиотеки, InitAcUiDLL (), который также обрабатывает AdUi инициализацию (через InitAdUiDLL () запрос); поэтому ваша прикладная потребность не повторно инициализирует AcUi или AdUi.
ПРЕДУПРЕЖДЕНИЕ! Хотя adui15.dll может быть вызван от приложений MFC-based других чем AutoCAD (или другие программы Autodesk), предназначенное использование библиотеки - Autodesk и третьими лицами явно для создания программного обеспечения, чтобы работать исключительно с AutoCAD, или другими изделиями Autodesk. Использование этого DLL для не- AutoCADа, автономные программы не разрешаются согласно лицензионному соглашению AutoCAD.
AdUi и AcUi
обеспечивают классы, которые осуществляют следующие особенности:
§ изменение размеров Диалога
§ постоянство данных Диалога
§ Табулированные диалоги
§ Расширяемые табулированные диалоги
§ Контекстно-зависимая справка и справка F1
§ взаимодействие Диалога с редактором рисунка AutoCAD
§ кнопки Bitmap, которые являются удобными
§ Статические растровые кнопки
§ кнопки Bitmap, которые являются, перетащат и опустить узлы
§ кнопки точечного рисунка Стиля инструментальной панели
§ кнопки Owner-draw, которые являются удобными
§ Диалог и управление поддерживают для стандарта ToolTips
§ Диалог и управление поддерживают для TextTips (которые отображают обрезанный текст)
§ Диалог и поддержка управления для DrawTips (владелец - тянут TextTips)
§ Заказная передача сообщений, включая проверку правильности данных
§ Поля со списком, которые отображают и позволяют выбор многого AutoCAD определенные элементы
§ Состыковывающиеся окна строки управления для использования с AutoCAD
§ Определенные в AutoCAD растровые кнопки (кнопки Pick и Select)
§ Специализированные средства редактирования, которые могут исполнять Определенную AutoCAD проверку правильности данных
§ Заказная передача сообщений, включая проверку правильности данных
Приложения ObjectArx могут быть созданы,
Приложения ObjectArx могут быть созданы, чтобы воспользоваться преимуществом Microsoft
Фундаментальный класс (MFC) библиотека. Эта глава обсуждает, как формировать ваш
Приложения ObjectArx, чтобы использовать MFC и как встроенный AutoCAD
MFC
система может использоваться, чтобы создать диалоги, которые ведут себя и работают
AutoCAD.
ObjectDBX SDK - интерфейс среди ведущих приложений, рисуя (.dwg) файлы, заказное приложение (.arx) файлы, и заказной объект (.dbx) файлы.
Введение Файла Проекта ATL
Обертки COM могут быть созданы как отдельный DLLS, или объединен с вашим ObjectARX-приложением. Оба метода используют ATL Microsoft AppWizard, чтобы упростить процесс. Отдельный DLL позволяет системе управлять ресурсами более эффективно; это может выпускать объекты COM, когда они не необходимы, даже если ObjectARX-приложение не может быть разгружено.
Основывать проект для обертки COM в отдельном DLL
1.
Удостоверятся axauto15.dll, который должен быть в том же самом каталоге как acad.exe, находится в вашем пути поиска файлов.
2. От меню Microsoft visual c ++ File, выберите Новый.
3. COM ATL Выбора AppWizard на позиции табуляции Projects и вводит проектное имя.
4. Выбирают тип сервера DLL. Дополнительные проектные назначения необязательные.
5. Выбирают Finish и OK.
6. От меню Insert или подручного меню представления Класса, выберите Новый Объект ATL.
7. Выбирают Простой Объект в категории Объектов и выбирают Затем.
8. Вводят C++ Короткое Имя на позиции табуляции Names; Мастер снабдит значения по умолчанию для остающихся имен.
9. На позиции табуляции Attributes, выберите Поддержку IErrorInfo.
10. Выбирают ХОРОШО.
11. От меню Project, выберите Назначения.
12. На C / C ++ позиция табуляции, выберите Язык C++ из раскрывающегося списка Категории, и выбор Позволяет обработку особых ситуаций.
13. На позиции табуляции Link, добавьте axauto15.lib, oleaprot.lib, и любые другие упомянутые ObjectARX библиотеки.
Выбирают OK.
Основывать проект, который объединяет обертку COM с существующим ObjectARX-приложением
1. Удостоверятся axauto15.dll, который должен быть в том же самом каталоге как acad.exe, находится в вашем пути поиска файлов.
2. От меню Microsoft visual c ++ File, выберите Новый.
3. COM ATL Выбора AppWizard на позиции табуляции Projects и вводит проектное{*строительное*} имя.
4. Выбирают тип сервера DLL. Дополнительные проектные{*строительные*} назначения необязательные.
5. Выбирают Конец и OK.
6. Добавляют весь CPP и H файлы от вашего ObjectARX-приложения.
7. Модифицируют ваши включаемые и библиотечные пути и DLL точку входа как соответствующий ObjectARX-приложению.
8. Модифицируют файл DEF, добавляя точки входа. Измените имя DLL, чтобы иметь ARX расширение.
9. В этой точке Вы должны быть способны компилировать, чтобы удостовериться, что ObjectARX-приложение формирует успешно.
10. От меню Insert или подручного меню представления Класса, выберите Новый Объект ATL.
11. Выбирают Простой Объект в категории Объектов и выбирают Затем.
12. Вводят C++ Короткое Имя на позиции табуляции Names; Мастер снабдит значения по умолчанию для остающихся имен.
13. На позиции табуляции Attributes, выберите Поддержку IErrorInfo.
14. Выбирают OK.
15. От меню Project, выберите Назначения.
16. На C / C ++ позиция табуляции, выберите Язык C++ из раскрывающегося списка Категории, и выбор Позволяет обработку особых ситуаций.
17. На позиции табуляции Link, добавьте axauto15.lib, oleaprot.lib, и любые другие упомянутые ObjectARX библиотеки.
18. Выбирают OK.
Введение Списков и Всплывающих Списков
Вы основываете списки, отображенные в списках, и во всплывающих списках, используя последовательность вызывает к трем функциям: ads_start_list (), ads_add_list (), и ads_end_list (). Как только список был создан, Вы можете исправлять это. Имеются три возможных операции, которые определены ads_start_list () параметр операции функции (чей значения показываются в круглых скобках в следующем списке).
§
Создают новый список (LIST_NEW).
После ads_start_list () запрос, Вы можете вызывать ads_add_list () неоднократно.
Каждый ads_add_list () запрос прибавляет новый элемент к списку. Конечная обработка списка, вызывая ads_end_list ().
§ Изменяют элемент в списке (LIST_CHANGE).
После ads_start_list (), вызовите ads_add_list () однажды заменить элемент, чей индекс был определен в ads_start_list () запрос. ( Если Вы называете ads_add_list () больше чем однажды, это заменяет тот же самый элемент снова.) В конце обработки вызывают ads_end_list ().
§ Добавляют элемент к списку (LIST_APPEND).
После ads_start_list (), вызовите ads_add_list () чтобы добавить элемент к концу списка. Если Вы продолжаете вызывать ads_add_list (), большее количество элементов добавлено в конец, пока Вы не вызываете ads_end_list ().
Независимо от которой списка операции Вы делаете, Вы должны вызвать три функции в правильной последовательности: ads_start_list(), тогда ads_add_list() (возможно больше чем однажды) и ads_end_list().
Списки наиболее легко представлены связанными буферами результатов, как показано в следующем примере:
struct resbuf *appnames, *rb;
// Initialize the appnames list here.
//
...
rb = appnames;
ads_start_list(hdlg, "selections", LIST_NEW, 0);
while (rb != NULL) {
ads_add_list(rb->resval.rstring);
rb = rb->rbnext;
}
ads_end_list();
Для коротких списков, проще передать индивидуальные строки. Список буфера результата не требован.
Значение list_box поля ввода - индекс (или индексы) отобранного элемента (или элементы). Если ваша программа должна знать фактический текст, связанный с индексом, это должно сохранить первоначальный список. Это должно также проследить изменения, сделанные методами, показанными в следующих примерах.
Элементы списка Добавления в конец подобны созданию нового списка. Например, appnames имеет 12 элементов в этом, и Вы хотите добавить другой список, вызвал newnames:
(start_list "selections" 2)
(mapcar ’add_list newnames)
(end_list)
В ObjectARX, Вы должны определить индексное значение, но ads_add_list () игнорирует это в добавляющейся операции.
struct resbuf *appnames, *newnames, *rb;
rb = newnames;
ads_start_list(hdlg, "selections", LIST_APPEND, 0);
while (rb != NULL) {
ads_add_list(rb->resval.rstring);
rb = rb->rbnext;
}
ads_end_list();
Изменение единственного элемента требует только одного ads_add_list () запрос. В следующем примере, Вы определяете индекс элемента, чтобы измениться:
ads_start_list(hdlg, "selections", LIST_CHANGE, 5);
ads_add_list("SURPRISE!");
ads_end_list();
Вы не можете удалять элемент списка или вставлять элемент без того, чтобы восстановить полный список.
Ввод Кнопки Изображения
Вы можете обрабатывать кнопку изображения просто как кнопка — то есть вызывать отдельное действие. Однако, PDB средство также дает Вам опцию определения областей кнопки так, чтобы принятое действие зависело, на которой части кнопки изображения пользователь выбирает. Механизм для этого прямой: действие кнопки изображения или повторный вызов возвращают (X, Y) местоположение, которое пользователь выбрал. Координаты - в пределах диапазона специфического поля ввода кнопки изображения (как возвращено функциями измерения). Ваше приложение должно назначить значение к местоположениям на поле ввода кнопки изображения, неявно определяя области изображения.
В следующем примере, кнопка изображения имеет два цветных образчика, созданные ads_fill_image (). Вы можете выбирать один или другой, в зависимости от которой области пользователь выбирает. Если кнопка изображения разделена горизонтально (темный выше, индикатор ниже), повторный вызов должен проверить только одно измерение. Не используйте структуру точки типа ads_point, чтобы сохранить координаты pickpoint, потому что их пропускают как длинные целые числа:
char result[31]; // Global char array
static void CALLB
pick_shade(ads_callback_packet cbpkt)
{
long threshold, pick_y = cbpkt->y;
ads_hdlg hdlg = cbpkt->dialog;
short x, y;
ads_dimensions_tile(hdlg, "image_sel", &x, &y);
threshold = y/2;
// Remember the origin at upper left.
//
if (pick_y > threshold)
strcpy(result, "Light");
else
strcpy(result, "Dark");
}
Выбор графики примитива
AcGixVectorTaker::message() метод поставляет вашему приложению информацией, требуемой, чтобы осуществить выбор примитива (выбор). Фактическое выполнение выбора зависит от того, как Вы осуществляете ваш дисплей.
Например, WhipView исполняет выборы против его 2-ого дисплейного файла.
Выполнение COM AutoCAD
OPM - по существу контроль, который анализирует информацию типа от объектов COM, чтобы определить их свойства. Когда объекты в рисунке отобраны, набор выборов преобразован в массив указателей IUnknown, представляющих объекты COM, которые переносят по словам все родные примитивы в AutoCAD. Эти обертки объекта COM - фундаментальная поддержка для ActiveX Автоматизации, связывают с помощью интерфейса и - основные объекты, с которыми OPM связывается.
Эти обертки объекта COM осуществляют IDISPATCH также как другие интерфейсы.
IDispatch - COM, связывают с помощью интерфейса использования OPM, чтобы получить и установить данные свойства. Это - также родное объектное представление в VB и VBA. Чтобы определять, который, свойства являются доступными для объекта, OPM, вызывают IDISPATCH:: GetTypeInfo (), который все обертки COM AutoCAD осуществляют.
Эта функция возвращает информацию типа для объекта (объект, который осуществляет ITYPEINFO). ITypeInfo - стандарт интерфейс Microsoft, который переносит по словам структуру данных, описывающую методы и свойства, доступные на том объекте. Коллекции информации типа, используемой VB и VBA, чтобы определить модель объекта ActiveX названы библиотеки типа.
OPM берет информацию свойства, и основанный на типе свойства, поскольку это определено в IDL, создает редактора свойства окно, соответствующее тому типу свойства. Например, если тип свойства числовой или текстовый, это создает окно редактирования. Если это - перечисление, это создает поле со списком с перечисленным списком значения. Если это - готовое свойство типа Цвета, Уровня, Типа линии, Lineweight, или других встроенных свойств, это создает стандарт drop-downs для тех, которые являются, тот же самый что касается Инструментальной панели Свойства объекта (OPT).
Статическая информация типа для каждого объекта COM - не единственный источник информации свойства для OPM. OPM также делает запрос объекта для нескольких других интерфейсов, чтобы управлять вещи типа классификации свойства, названия значения свойства для раскрывающихся списков, и инициализация диалогов для редактирования " в собственность " (типа диалогов кнопки замещающего знака). Они будут описаны подробно позже в этой секции, но будут упомянуты все вместе как “ flavoring ” интерфейсы.
Выполнение итераций через Вершину в Ломаной линии
Следующее выполнение итераций показов примера через вершину в ломаной линии, использующей вершину iterator. Это тогда печатает координаты для каждой вершины.
// Принимает объект ID AcDb2dPolyline, открывает это, и получает вершину iterator.
// Это тогда выполняет итерации через вершину, распечатывая местоположение вершины.
void
iterate(AcDbObjectId plineId)
{
AcDb2dPolyline *pPline;
acdbOpenObject(pPline, plineId, AcDb::kForRead);
AcDbObjectIterator *pVertIter= pPline->vertexIterator();
pPline->close(); // Finished with the pline header.
AcDb2dVertex *pVertex;
AcGePoint3d location;
AcDbObjectId vertexObjId;
for (int vertexNumber = 0; !pVertIter->done();
vertexNumber++, pVertIter->step())
{
vertexObjId = pVertIter->objectId();
acdbOpenObject(pVertex, vertexObjId,
AcDb::kForRead);
location = pVertex->position();
pVertex->close();
acutPrintf("\nVertex #%d’s location is"
" : %0.3f, %0.3f, %0.3f", vertexNumber,
location[X], location[Y], location[Z]);
}
delete pVertIter;
}
Выполнение итераций через Запись таблицы блоков
Следующий пример демонстрирует, как выполнить итерации через элементы в записи таблицы блоков и распечатывать элементы.
PrintAll () функция открывает таблицу блоков для чтения, и затем это открывает имя блока, снабженное пользователем. Новый iterator шагает через записи таблицы блоков. Если запись содержит примитив, iterator печатает сообщение относительно примитива.
void
printAll()
{
int rc;
char blkName[50];
rc = acedGetString(Adesk::kTrue,
"Enter Block Name <CR for current space>: ",
blkName);
if (rc != RTNORM)
return;
if (blkName[0] == ’\0’) {
if (acdbHostApplicationServices()->workingDatabase()
->tilemode() == Adesk::kFalse) {
struct resbuf rb;
acedGetVar("cvport", &rb);
if (rb.resval.rint == 1) {
strcpy(blkName, ACDB_PAPER_SPACE);
} else {
strcpy(blkName, ACDB_MODEL_SPACE);
}
} else {
strcpy(blkName, ACDB_MODEL_SPACE);
}
}
AcDbBlockTable *pBlockTable;
acdbHostApplicationServices()->workingDatabase()
->getSymbolTable(pBlockTable, AcDb::kForRead);
AcDbBlockTableRecord *pBlockTableRecord;
pBlockTable->getAt(blkName, pBlockTableRecord,
AcDb::kForRead);
pBlockTable->close();
AcDbBlockTableRecordIterator *pBlockIterator;
pBlockTableRecord->newIterator(pBlockIterator);
for (; !pBlockIterator->done(); pBlockIterator->step())
{
AcDbEntity *pEntity;
pBlockIterator->getEntity(pEntity, AcDb::kForRead);
AcDbHandle objHandle;
pEntity->getAcDbHandle(objHandle);
char handleStr[20];
objHandle.getIntoAsciiBuffer(handleStr);
const char *pCname = pEntity->isA()->name();
acutPrintf("Object Id %lx, handle %s, class %s.\n",
pEntity->objectId(), handleStr, pCname);
pEntity->close();
}
delete pBlockIterator;
pBlockTableRecord->close();
acutPrintf("\n");
}
Выполнение итераций по Таблицам
Код в следующем примере создает iterator, который идет через записи таблицы идентификаторов в linetype таблице. Это получает каждую запись, открывает это для чтения, получает имя linetype, закрывает запись, и затем печатает имя linetype. В конец, программа удаляет iterator.
void
iterateLinetypes()
{
AcDbLinetypeTable *pLinetypeTbl;
acdbHostApplicationServices()->workingDatabase()
->getSymbolTable(pLinetypeTbl, AcDb::kForRead);
// Create a new iterator that starts at table
// beginning and skips deleted.
//
AcDbLinetypeTableIterator *pLtIterator;
pLinetypeTbl->newIterator(pLtIterator);
// Walk the table, getting every table record and
// printing the linetype name.
//
AcDbLinetypeTableRecord *pLtTableRcd;
char *pLtName;
for (; !pLtIterator->done(); pLtIterator->step()) {
pLtIterator->getRecord(pLtTableRcd, AcDb::kForRead);
pLtTableRcd->getName(pLtName);
pLtTableRcd->close();
acutPrintf("\nLinetype name is: %s", pLtName);
free(pLtName);
}
delete pLtIterator;
pLinetypeTbl->close();
}
Выполнение итераций по Входам Словаря
Iterator класс для словарей - AcDbDictionaryIterator. Следующая выборка кода получает словарь (ASDK_DICT) от названного объектного словаря.
Это тогда использует словарь iterator, чтобы шагнуть через входы словаря и печатать значение сохраненного целого числа. Наконец, это удаляет iterator и закрывает словарь.
void
iterateDictionary()
{
AcDbDictionary *pNamedobj;
acdbHostApplicationServices()->workingDatabase()
->getNamedObjectsDictionary(pNamedobj, AcDb::kForRead);
// Get a pointer to the ASDK_DICT dictionary.
//
AcDbDictionary *pDict;
pNamedobj->getAt("ASDK_DICT", (AcDbObject*&)pDict,
AcDb::kForRead);
pNamedobj->close();
// Get an iterator for the ASDK_DICT dictionary.
//
AcDbDictionaryIterator* pDictIter = pDict->newIterator();
AsdkMyClass *pMyCl;
Adesk::Int16 val;
for (; !pDictIter->done(); pDictIter->next()) {
// Get the current record, open it for read, and
// print its data.
//
pDictIter->getObject((AcDbObject*&)pMyCl,
AcDb::kForRead);
pMyCl->getData(val);
pMyCl->close();
acutPrintf("\nintval is: %d", val);
}
delete pDictIter;
pDict->close();
}
Выполнение Объектов Автоматизации
Следующие Определенные автохамом интерфейсы поддержаны объектами COM в API Автоматизации, которые представляют объект в базе данных:
IacadBaseObject |
Поддерживает связь к AcDbObject через AcDbObjectId. | ||
IacadObjectEvents |
Исходный интерфейс, который уведомляет клиентов COM когда AcDbObject изменился. | ||
IretrieveApplication |
Используемым, чтобы сообщить объект COM, что возвращаться для Прикладного свойства. | ||
IacadObject |
Выставляет все общие свойства и методы, которые обращаются к каждому объекту в базе данных. | ||
IacadEntity |
Выставляет все общие свойства и методы, которые обращаются к каждому примитиву в базе данных. (Только применимый для AcDbEntity –наследованных классов.) |
Следующие интерфейсы - не AutoCAD, определенный, но требованы для надлежащего поведения:
Idispatch |
Позволяет поздно обязывать. Броузеры типа OPM требуют этого интерфейса. | ||
IconnectionPointContainer |
Используемым, чтобы сохранить список точек соединения. | ||
IconnectionPoint |
Используемым, чтобы позволить клиентов COM, чтобы просить о уведомлении. | ||
IsupportErrorInfo |
Сообщает клиентам COM что объектная информация ошибки поддержек. |
Если Вы создаете класс COM, чтобы представить AcDbObject-полученный класс, Вы будете должны осуществить все эти интерфейсы.
Выполнение Приложений ObjectArx от AutoLISP
Приложение ObjectArx может определять набор функций, известных к AutoLISP как внешние функции, используя acedDefun (). После того, как приложение загружено, Вы можете вызывать внешнюю функцию точно, поскольку Вы можете вызывать встроенную или определяемую пользователем функцию AutoLISP. Переменные AutoLISP можно пропускать как параметры к внешней функции, и внешняя функция может возвращать результат.
Внешняя функция может также запрашивать пользователя вводить данные, или от клавиатуры или, определяя пункты{*точки*} или объекты{*цели*} с устройством управления позицией, и внешняя функция может устанавливать Windows или AutoCAD платформа-независимая справка.
Внешняя функция может быть вызвана функцией AutoLISP, также как в интерактивном режиме. Приложения ObjectArx не могут вызывать функции AutoLISP. Приложение ObjectArx может отыскивать и устанавливать значение символов AutoLISP (тип данных символа должен быть распознаваемый к программе C++).
Приложение ObjectArx может определять новую команду AutoCAD с тем же самым C:XXX соглашением как AutoLISP. Вы вызываете внешнюю функцию, вводя ее название{*имя*} в Приглашении ко вводу команды, без круглых скобок.
Определение внешней функции заменяет любое предыдущее определение того же самого названия{*имени*}. Если два Приложения ObjectArx определяют функции с тем же самым названием{*именем*}, функция в первом приложении, которое будет загружено потеряна; если Вы разгружаете второе приложение, Вы не можете вызывать{*называть*} двойную функцию.
Вырождение
Некоторые операции могут приводить к созданию выродившихся примитивов. Выродившееся означает, что, хотя заканчивающийся объект принадлежит специфическому классу, его геометрия больше не может соответствовать требованиям того класса. Например, если Вы начинаете с круговой дуги и затем устанавливаете ее угол начала, равняются ее конечному углу, Вы фактически имеете точку вместо круговой дуги. Геометрически, объект - точка, но ее тип во время выполнения - все еще круговая дуга. Вы можете использовать один из isDegenerate () функции, чтобы определить,является ли объект выродившимся. Первая версия каждой пары функций возвращает тип. Вторая версия возвращает невыродившийся объект различного типа во время выполнения. В предыдущем примере, это возвратило бы точку:
Adesk::Boolean
AcGeCurve2d::isDegenerate(
AcGe::EntityId& degenerateType,
const AcGeTol&=AcGeContext::gTol) const;
Adesk::Boolean
AcGeCurve2d::isDegenerate(
AcGeEntity2d*& pConvertedEntity,
const AcGeTol&=AcGeContext::gTol) const;
Adesk::Boolean
AcGeCurve3d::isDegenerate(
AcGe::EntityId& degenerateType,
const AcGeTol&=AcGeContext::gTol) const;
Adesk::Boolean
AcGeCurve3d::isDegenerate(
AcGeEntity3d*& pConvertedEntity,
const AcGeTol&=AcGeContext::gTol) const;
Высвечивание Вложенных Блочных Ссылок
Пример, который следует за показами, высвечивающими вложенные блочные ссылки{*справочники*}. Как показано в следующем числе{*рисунке*}, пример создает шесть примитивов: три polys (заказной примитив) и три поля. Это также создает три блочных ссылки{*справочников*} (вставки).
Вставьте 3 (ins3) - вставка блока, который содержит poly3 и box3. Вставьте 2 (ins2) - вставка блока, который содержит poly2, box2, и ins3. Вставьте 1 (ins1) - вставка блока, который содержит poly1, box1, и ins2.
После того, как вставки созданы, пример высвечивает различные компоненты.
void
createInsert()
{
// Create a nested insert and try highlighting its
// various subcomponents.
//
// There are six entities in total -- three polys and
// three boxes (solids). We’ve named them: poly1, poly2,
// poly3, and box1, box2, box3. We also have three
// inserts: ins1, ins2, ins3.
//
// ins3 is an insert of a block that contains (poly3, box3)
// ins2 is an insert of a block that contains (poly2, box2,
// ins3).
// ins1 is an insert of a block that contains (poly1, box1,
// ins2).
//
// Let's create these entities first.
//
// Polys
//
AsdkPoly *poly1, *poly2, *poly3;
AcGeVector3d norm(0, 0, 1);
if ((poly1=new AsdkPoly)==NULL){
acutPrintf("\nOut of Memory.");
return;
}
if (poly1->set(AcGePoint2d(2, 8),AcGePoint2d(4, 8), 6, norm, "POLY1",0) != Acad::eOk){
acutPrintf("\nCannot create object with given parameters.");
delete poly1;
return;
}
if ((poly2=new AsdkPoly)==NULL){
acutPrintf("\nOut of Memory.");
delete poly1;
return;
}
if (poly2->set(AcGePoint2d(7, 8), AcGePoint2d(9, 8), 6, norm, "POLY2",0) != Acad::eOk){
acutPrintf("\nCannot create object with given parameters.");
delete poly1;
delete poly2;
return;
}
if ((poly3=new AsdkPoly)==NULL){
acutPrintf("\nOut of Memory.");
delete poly1;
delete poly2;
return;
}
if (poly3->set(AcGePoint2d(12, 8),AcGePoint2d(14, 8), 6, norm, "POLY3",0)!=Acad::eOk){
acutPrintf("\ nCannot create object with given parameters.");
delete poly1;
delete poly2;
delete poly3;
return;
}
postToDb(poly1);
postToDb(poly2);
postToDb(poly3);
// Boxes
//
AcDb3dSolid *box1, *box2, *box3;
box1 = new AcDb3dSolid();
box2 = new AcDb3dSolid();
box3 = new AcDb3dSolid();
box1->createBox(2, 2, 2);
box2->createBox(2, 2, 2);
box3->createBox(2, 2, 2);
AcGeMatrix3d mat;
mat(0, 3) = 2; mat(1, 3) = 2;
box1->transformBy(mat);
mat(0, 3) = 7; mat(1, 3) = 2;
box2->transformBy(mat);
mat(0, 3) = 12; mat(1, 3) = 2;
box3->transformBy(mat);
postToDb(box1);
postToDb(box2);
postToDb(box3);
// Inserts
//
// Arguments to BLOCK are:
// blockname,
// insert point,
// select objects,
// empty string for selection complete
// Arguments to INSERT are:
// blockname,
// insertion point,
// xscale,
// yscale,
// rotation angle
//
acedCommand_command(RTSTR, "_globcheck", RTSHORT, 0, RTNONE);
acedCommand(RTSTR, "BLOCK", RTSTR, "blk3", RTSTR, "0,0",
RTSTR, "14,8", RTSTR, "11,1", RTSTR, "",
RTNONE);
acedCommand(RTSTR, "INSERT", RTSTR, "blk3", RTSTR,
"0,0", RTSHORT, 1, RTSHORT, 1, RTSHORT,
0, RTNONE);
acedCommand(RTSTR, "BLOCK", RTSTR, "blk2", RTSTR, "0,0",
RTSTR, "9,8", RTSTR, "6,1", RTSTR, "11,1",
RTSTR, "", RTNONE);
acedCommand(RTSTR, "INSERT", RTSTR, "blk2", RTSTR,
"0,0", RTSHORT, 1, RTSHORT, 1, RTSHORT,
0, RTNONE);
acedCommand(RTSTR, "BLOCK", RTSTR, "blk1", RTSTR, "0,0",
RTSTR, "4,8", RTSTR, "1,1", RTSTR, "6,1",
RTSTR, "", RTNONE);
acedCommand(RTSTR, "INSERT", RTSTR, "blk1", RTSTR,
"0,0", RTSHORT, 1, RTSHORT, 1, RTSHORT,
0, RTNONE);
return;
}
void
hilitInsert()
{
Adesk::Boolean interrupted = Adesk::kFalse;
acutPrintf("\nSelect an insert");
Acad::ErrorStatus es = Acad::eOk;
AcDbEntity *ent = NULL;
AcDbEntity *ent2 = NULL;
AcDbBlockReference *blRef = NULL;
AcDbObjectId objectId, blRefId;
ads_name ename, sset;
for (;;) {
switch (acedSSGet(NULL, NULL, NULL, NULL, sset)) {
case RTNORM:
{
struct resbuf *rb;
if (acedSSNameX(&rb, sset, 0) != RTNORM) {
acutPrintf("\n acedSSNameX failed");
acedSSFree(sset);
return;
}
int sel_method;
ads_name subname;
short marker;
AcGePoint3d pickpnt;
AcGeVector3d pickvec;
if (!extractEntityInfo(rb,
sel_method,
ename,
subname,
marker,
pickpnt,
pickvec)) {
acutPrintf("\nextractEntityInfo failed");
acedSSFree(sset);
return;
}
acedSSFree(sset);
assert(marker != 0);
if (marker == 0) {
acutPrintf("\nmarker == 0");
return;
}
// Get the insert first.
//
AOK(acdbGetObjectId(blRefId, ename));
AOK(acdbOpenAcDbEntity(ent, blRefId,
AcDb::kForRead));
assert(ent != NULL);
blRef = AcDbBlockReference::cast(ent);
if (blRef == NULL) {
acutPrintf("\nNot an insert.");
AOK(ent->close());
continue;
}
struct resbuf *insStack;
ads_point pickpoint;
ads_matrix adsmat;
pickpoint[0] = pickpnt[0];
pickpoint[1] = pickpnt[1];
pickpoint[2] = pickpnt[2];
// Now get details on the entity that was
// selected.
//
if (acedNEntSelP(NULL, ename, pickpoint, TRUE,
adsmat, &insStack) != RTNORM)
{
acutPrintf("\nFailure in acedNEntSelP");
return;
}
assert(insStack != NULL);
AOK(acdbGetObjectId(objectId, ename));
AOK(acdbOpenAcDbEntity(ent2, objectId,
AcDb::kForRead));
assert(ent2 != NULL);
// Make an array of AcDbObjectIds from the
// insertStack. Don’t use the "smart array"
// AcDbObjectIdArray class, because the
// getSubentPathsAtGsMarker() function expects argument
// eight to be of type AcDbObjectId*. Just
// make room for approximately 100 IDs in the array.
//
AcDbObjectId *idArray = new AcDbObjectId[100];
int count = 0;
struct resbuf *rbIter = insStack;
AcDbObjectId objId;
acdbGetObjectId(objId, ename);
idArray[count++] = objId;
while (rbIter != NULL) {
ename[0] = rbIter->resval.rlname[0];
ename[1] = rbIter->resval.rlname[1];
acdbGetObjectId(objId, ename);
idArray[count++] = objId;
rbIter = rbIter->rbnext;
}
count--;
acutRelRb(insStack);
// First, we’ll highlight an edge.
//
int numPaths;
AcDbFullSubentPath *subentPaths;
AcGeMatrix3d xform;
es = blRef->getSubentPathsAtGsMarker(
AcDb::kEdgeSubentType,
marker,
pickpnt,
xform,
numPaths,
subentPaths,
count,
idArray);
assert(numPaths == 1);
// Highlight and unhighlight the selected edge.
//
acutPrintf("\nHighlighting the first edge.");
es = blRef->highlight(subentPaths[0]);
pressEnterToContinue();
es = blRef->unhighlight(subentPaths[0]);
// If this is a solid, it will have faces.
// In this case, let’s highlight them.
//
if(ent2->isKindOf(AcDb3dSolid::desc())) {
es = blRef->getSubentPathsAtGsMarker(
AcDb::kFaceSubentType,
marker,
pickpnt,
xform,
numPaths,
subentPaths,
count,
idArray);
assert(numPaths == 2);
// Highlight and unhighlight the selected
// faces.
//
acutPrintf("\nHighlighting the first"
" face.");
es = blRef->highlight(subentPaths[0]);
pressEnterToContinue();
es = blRef->unhighlight(subentPaths[0]);
acutPrintf("\nHighlighting the next face.");
es = blRef->highlight(subentPaths[1]);
pressEnterToContinue();
es = blRef->unhighlight(subentPaths[1]);
}
delete []subentPaths;
// Now, let’s highlight the whole entity.
//
acutPrintf("\nHighlighting the entire entity");
AcDbFullSubentPath subPath;
for (int i = count; i >= 0; i--) {
subPath.objectIds().append(idArray[i]);
}
es = blRef->highlight(subPath);
pressEnterToContinue();
es = blRef->unhighlight(subPath);
// Finally, let’s highlight each enclosing
// insert.
//
for (i = count -1; i >= 0; i --) {
subPath.objectIds().removeAt(
subPath.objectIds().length() - 1);
acutPrintf("\nHighlighting insert layer %d",
i + 1);
blRef->highlight(subPath);
pressEnterToContinue();
es = blRef->unhighlight(subPath);
}
} // case RTNORM
break;
case RTNONE:
case RTCAN:
return;
default:
continue;
} // switch
break;
} //for (;;)
AOK(ent->close());
AOK(ent2->close());
return;
}
Взаимодействие с AutoCAD
Взаимодействие Пользователя (типа acedGetPoint) от запроса Автоматизации должно быть обернуто вокруг ряда ObjectARX ВЫЗОВОВ API. Это позволяет Вам сохранять AutoCAD “состояние” перед взаимодействием и затем восстанавливать это впоследствии. Это также гарантирует, что любой другой из -процесса запросы Автоматизации отклонены для продолжительности вашего взаимодействия. Это предотвращает другого клиента Автоматизации от изменения командной строки или базы данных, в то время как Вы ожидаете ввод пользователя.
ObjectARX API, чтобы использовать при взаимодействии с пользователем включают следующие функции:
Adesk::Boolean acedSetOLELock(int handle, int flags=0);
Adesk::Boolean acedClearOLELock(int handle);
void acedPostCommandPrompt();
Например:
// Получить точку в AutoCAD, даже при том, что точка не используется.
//
STDMETHODIMP CMyApp::GetPoint()
{
// Установление блокировки сообщает AutoCAD, чтобы отклонить любой другой из -процесса запросы
// Автоматизации. Если этот запрос сделан от неизвестного контекста (например, не нормалью AutoCAD
// зарегистрированной командой или lisp), то это также сохраняет поток состояние AutoCAD.
//
if (acedSetOLELock(5) != Adesk::kTrue)
{
return E_FAIL;
}
// Do the input acquisition (interaction) == Делайте входное приобретение (взаимодействие).
//
ads_point result;
if(ads_getpoint(NULL, "Pick a point: ", result) != RTNORM)
{
return E_FAIL;
}
// Clear the lock to allow out-of-process Automation
// requests to be accepted again. If the AutoCAD state was saved
// during the call to acedSetOLELock(), then the saved state is
// restored.
// Очистить блокировку, чтобы позволить из -процесса запросам Автоматизации быть принятым
// снова. Если состояние AutoCAD было сохранено в течение запроса к acedSetOLELock (), то
// сохраненное состояние восстановлено.
//
acedClearOLELock(5);
//Вынуждает AutoCAD восстанавливать изображение приглашения ко вводу команды..
//
acedPostCommandPrompt();
return S_OK;
}
Взаимодействие с Множественными документами
Эта секция описывает три основных уровня взаимодействия, ObjectARX-приложение должно иметь с множественными документами в пределах данного обращения команды. В следующих трех подразделах, " нормальная команда " является или встроенной командой AutoCAD, командой AcEd-registered, или функцией AutoLISP, подчиненной к ограничениям на использование AcDocManager- > curDocument ().
Взаимодействие с Редактором AutoCAD
ObjectARX обеспечивает классы и функции элемента, чтобы взаимодействовать с
редактором AutoCAD. Вы можете регистрировать команды в AutoCAD для обработки их как встроенных команд. Ваше приложение может получать и отвечать на уведомление относительно разнообразных событий, которые происходят в AutoCAD.
Взрыв Примитива
Вы должен перегрузить explode() функция заказного объекта для AutoCAD командует BHATCH и EXPLODE, чтобы работать. Ваш, чтобы explode () функция должна сломать объект в менее комплексные объекты. Если заканчивающиеся объекты - не, родные объекты, ваша функция должны возвратить eExplodeAgain.
Это заставит BHATCH рекурсивно называть explode() функцию на объектах, которые Вы возвращаетесь, пока они не были сокращены к родным объектам. Родные объекты, на которые BHATCH может работать непосредственно - AcDb2dPolyline, AcDb3dPolyline, AcDbPolyline, AcDbText, AcDbMText, AcDbShape, AcDbTrace, AcDbSolid, AcDbFace, AcDbViewport, AcDbFcf, AcDbDimension, AcDbRegion, AcDbBlockReference, и AcDbHatch.
WblockClone ()
Имеются три версии AcDbDatabase:: wblock ():
1 WBLOCK*
Acad:: ErrorStatus
AcDbDatabase::wblock(AcDbDatabase*& POutputDatabase)
2 WBLOCK определяемого пользователем блока
Acad:: ErrorStatus
AcDbDatabase::wblock(AcDbDatabase*& POutputDatabase, AcDbObjectId nObjId)
3 WBLOCK набора выборов
Acad:: ErrorStatus
AcDbDatabase::wblock(AcDbDatabase*& POutputDatabase, const AcDbObjectIdArray& PIdSet, const AcGePoint3d& PPoint3d)
Одно из основных внутренних различий между этими тремя версиями wblock - их обработка пространства модели и пространства листа AcDbBlockTableRecords. Поскольку полная база данных клонируется в одной версии, все примитивы в пространстве модели и пространстве листа клонированы наряду с их содержащей бумагой и пространством модели AcDbBlockTableRecords. Однако, в версиях два и три, намерение должно клонировать только отобранный набор примитивов. Хотя пространство модели и пространство листа AcDbBlockTableRecords обработаны, они используют “ поверхностный клон, ”, который в свою очередь не клонирует все примитивы, содержащиеся в пространстве модели и пространстве листа.
Даже при том, что пространство модели и блоки пространства листа были клонированы в версиях два и три, они пусты. Поэтому, не только приемлемо вызвать AcDbBlockTableRecord:: AppendAcDbEntity () чтобы разместить клонированные примитивы в них, необходимо делать так. (Это - исключение к использованию AcDbBlocKTableRecord:: AppendAcDbEntity () на AcDbBlockTableRecords, чей ID - в состоянии непрерывного изменения). Также, в обеих версиях два и три, примитивы будут иметь набор isPrimary к Adesk:: kTrue, когда они получают их wblockClone () запрос.
Это - то, потому что внутренний код индивидуально клонирует примитивы набора выборов, или примитивов отобранного AcDbBlockTableRecord. Это не клонирует AcDbBlockTableRecord непосредственно. (Примитивы во вложенных блоках, однако, будут все еще иметь набор isPrimary к Adesk:: kFalse). Это поведение полезно, как будет замечено в следующей секции в случае 1. Это сохраняет приложения от необходимости знать, что какая операция WBLOCK встречается.
Имеются несколько основных правила, чтобы иметь в виду:
1 Никогда не использовать AcDbBlocKTableRecord::AppendAcDbEntity() в течение WBLOCK*. Если Вы создали новые примитивы, Вы должны сохранить их в памяти, наряду с ID их будущего владельца, и затем добавлять их после AcEdItorReactor::endDeepClone(). Это также применяется к добавлению в конец объектов к AcDbDictionaries, ломаным линиям, polyfacemeshes, polygonmeshes, и блок-ссылкам.
2 В других двух формах WBLOCK, только используют AcDbBlocKTableRecord::ApPendAcDbEntity() при добавлении в конец к пространству модели или пространству листа. Но с тем исключением, все другие ограничения, упомянутые для WBLOCK* все еще применяются.
WhipView
WhipView библиотечные орудия AcGixView и AcGixVectorTaker на
вершине WHIP! Графический акселератор. WHIP! Является графическим акселератором с 2-ым кэшем изображения, сформированным на вершине HEIDI технологии Autodesk. Это экспортирует единственную функцию API, acgixAllocateWhipView (), который создает и возвращает образец AcGixBlockView. Возвращенный образец может использоваться таким же образом как любой другой AcGixBlockView. SimpleView библиотека демонстрирует создание рисунка видов, использующих WhipView. Из-за дисплейного файла, WhipView способен обслужить некоторые действия подобно кастрюле и изменять масштаб изображения без потребности в перегенеральном. Это дает лучшее работу, чем прямое выполнение GDI SimpleView.
WhipView снабжен в двоичной форме только, и состоит из несколько DLLs и файлах поддержки, представляющих WhipView библиотеку, WHIP! Компонент, HEIDI, и HDI драйверы устройства. WhipView может использоваться независимым от SimpleView, если бы не необходимые элементы AcGixBlockView. Прямое использование WHIP!, HEIDI, и HDI драйверы ObjectDBX разработчиками не поддержан.
Они снабжены в двоичной форме только, без связанных заголовков.
API WhipView модуля состоит из единственной точки входа, которая имеет следующую сигнатуру:
AcGixBlockView* acgixAllocateWhipView ();
Эта функция явно объявлена внешней и используется в SimpleView исходном модуле AcGixSimpleViewManager.cpp. Не имеется никакого экспортируемого файла заголовка, который объявляет acgixAllocateWhipView ().
Чтобы многократно использовать этот элемент, Вы должны брать AcGixBlockView, столь же определенный и так много еще SimpleView комплекса, что необходимо. Быть Предупредите, однако, что AcGixBlockView довольно усложнен и использует многое из остальной части SimpleView. Выполнение наиболее легко сделано, если Вы оставляете SimpleView в по существу неизменном состоянии.
WhipView клиенты связываются непосредственно с AcGixWhipView.lib. WhipView требует AcDb.dll, heidi3.dll, dllong3.dll, и HDI файлы, снабженные в каталоге выпусков.
BAT файл пользователя, чтобы включить
Вы должны модифицировать AUTOEXEC. BAT файл пользователя, чтобы включить “aliased” (или короткий) имя пути, потому что переменная ПУТИ не будет обрабатывать пробелы. В то время как пути к приложению должны удовлетворить, строго рекомендуется, чтобы Вы модифицировали пользователя AUTOEXEC.BAT из-за известных проблем с автоматизацией (отнесите к Microsoft KnowledgeBase статью Q148375).
Гарантируйте умные модификации путей
При модифицировании пользователя AUTOEXEC.BAT пожалуйста, быть прилежный относительно изменения входа пути, если вход пути - уже там. Что должно быть предотвращено, только изменяет ПУТЬ без отношения к любому из этих условий:
§
путь - уже там.
§ Вы воздействуют на другие назначения пути в пакетном файле.
При модифицировании значения ПУТИ, независимо от того, который операционная система Вы имеете дело, ваш инсталлятор должен запросить пользователя перезагружаться так, чтобы изменение пути было должным образом зарегистрировано после того, как инсталляция полна.
Autodesk обеспечивает сценарий InstallShield ниже как неполный пример сильного модифицирования пути:
function AdUpdateAUTOEXEC (szSharedPath)
STRING szRootPath, szBatchName, szBatchFile,
szBackupName,szTestLine,szCheckForPathLine;
NUMBER nReturn, nvHandle;
STRING szOutput;
begin
szOutput = "SET PATH=%PATH%;" + szSharedPath;
// Obtain the filename of the system batch file.
BatchGetFileName (szBatchFile);
ParsePath(szRootPath, szBatchFile, PATH);
// Make sure we’re pointing at the root of the system
VarSave(SRCTARGETDIR);
TARGETDIR = szRootPath;
SRCDIR = szRootPath;
// See if we have an AUTOEXEC.
if (Is(FILE_EXISTS,szBatchFile) = FALSE) then
// If we don’t, just write ’ours’ out and no more
OpenFileMode (FILE_MODE_NORMAL);
ParsePath(szBatchFile,szBatchFile,FILENAME);
CreateFile (nvHandle,SRCDIR,szBatchFile);
WriteLine (nvHandle, szOutput);
CloseFile (nvHandle);
bNeedReboot = TRUE;
else
ParsePath(szBatchName, szBatchFile, FILENAME_ONLY);
szBackupName = szBatchName + ".ADK";
ParsePath(szBatchFile, szBatchFile, FILENAME);
OpenFileMode(FILE_MODE_NORMAL);
nReturn = OpenFile (nvHandle, SRCDIR, szBatchFile);
if (nReturn = 0 ) then
// Spin down to find the non-blank last line in
// the file
while (nReturn = 0 )
nReturn = GetLine(nvHandle, szTestLine);
if (StrLength(szTestLine) > 0) then
szCheckForPathLine = szTestLine;
endif;
endwhile;
CloseFile(nvHandle);
// We now have the last text entry in the batch
// file.
if (StrFind(szCheckForPathLine,szSharedPath) < 0) then
Disable(LOGGING);
// Backup up the original
nReturn = CopyFile (szBatchFile, szBackupName);
Enable(LOGGING);
if (nReturn = 0 ) then
OpenFileMode (FILE_MODE_APPEND);
OpenFile(nvHandle,SRCDIR,szBatchFile);
WriteLine(nvHandle,"");
WriteLine(nvHandle,szOutput);
CloseFile(nvHandle);
bNeedReboot = TRUE;
endif;
endif;
endif;
endif;
VarRestore(SRCTARGETDIR);
end;
Windows NT
Вы должны также модифицировать Путь Системы в системном реестре. Это может быть найдено под
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment. Значение Пути, сохраненное там должно измениться, чтобы включить ваш путь. Обратите внимание, что эта строка - тип значения REGDB_STRING_EXPAND.
WorldDraw () Функция
WorldDraw() функция - первичный механизм для drawable, чтобы отобразить себя. От этого повторного вызова drawable использует AcGiSubEntityTraits и интерфейсы AcGiWorldGeometry, чтобы сообщить AcGi
выполнение, как этот drawable должен быть представлен во всех активных областях просмотра. Для информации, которая является определенной к некоторым областям просмотра, viewportDraw () повторный вызов обеспечивается (см. “ viewportDraw () Функцию ” на странице 688).
AcDbEntity:: worldDraw () функция берет указатель на объект AcGiWorldDraw. AcGiWorldDraw - контейнерный класс для AcGi геометрии и объектов черт. Определенно, AcGiWorldDraw содержит два других объекта:
§
AcGiWorldGeometry
§ AcGiSubEntityTraits
К объекту AcGiWorldGeometry можно обращаться изнутри worldDraw() используя AcGiWorldDraw::geometry(), к объекту AcGiSubEntityTraits можно обращаться, используя AcGiWorldDraw::subEntityTraits().
Объект AcGiWorldGeometry записывает векторы на дисплей AutoCAD, использующий его набор рисунка примитивов. Примитив - команда с самым низким уровнем, имел обыкновение рисовать графические примитивы. Мировой объект геометрии имеет следующие функции для рисунка примитивов в мировых координатах, которые унаследованы от AcGiGeometry:
§ Circle
§ Circular arc
§ Polyline
§ Polygon
§ Mesh
§ Shell
§ Text
§ Xline
§ Ray
§ Draw
Рисующий метод позволяет Вам определять другой drawable, который нужно использовать как часть вашей геометрии. Это могло бы быть другой примитив или в оперативной памяти drawable.
AcGi использует тот же самый setAttributes (), worldDraw (), и viewportDraw () логика на этом объекте, поскольку это использует на вашем объекте.
Объект AcGiSubEntityTraits устанавливает графические атрибуты со значением, использующие его набор функций черт:
§ Color
§ Layer
§ Linetype
§ Polygon fill type
§ Selection marker
§ Line weight (вес Линии)
§ Thickness (Толщина)
§ Графическое имя стиля (не должен измениться в течение worldDraw () или viewportDraw ())
Xrecord Объекты
Xrecord объект - встроенный объектный класс с именем DXF “XRECORD”, который сохраняет и управляет произвольными потоками данных, представ внешне в результате буферизуют список, составленный из групп DXF с “ объект нормали ” группы (то есть не - xdata коды группы), в пределах от 1 до 369.
ПРЕДУПРЕЖДЕНИЕ! Xrecord объект разработан{*предназначен*} в пути, который не будет оскорблять более ранние версии AutoCAD; однако, xrecord объект исчезнет при создании DXF файла от предварительного выпуска 13c4 уровень AutoCAD.
Xrecord объекты - универсальные объекты, предназначенные для использования приложениями ObjectARX и AutoLISP. Этот класс позволяет приложениям создавать и сохранять произвольные объектные структуры произвольных списков буфера результата не-графической информации, полностью отделяются от примитивов. Корневой владелец для всех определенных приложением объектов является или словарью имен объектов, которая принимает любой тип AcDbObject как вход, включая AcDbXrecord, или словарь расширения любого объекта.
Приложения, как ожидается, будут использовать уникальные названия{*имена*} входа в словари имен объектов. Логика использования словари имен объектов или имени входа словаря расширения{*продления*} подобна таковому имени REGAPP. Фактически, REGAPP названия{*имена*} совершенен для использования как названия{*имена*} входа при добавлении в конец определенных приложением объектов к базе данных или специфическому объекту.
Использование xrecord объектов представляет существенное упрощение относительно текущей практики назначения xdata к примитивам. Поскольку xrecord объект не должен быть связан с примитивом, Вы больше не должны создать фиктивные примитивы (фиктивные примитивы часто использовались, чтобы обеспечить большее количество участка памяти для xdata), или примитивов на закрепемых уровнях.
Приложения теперь способны делать следующее:
Защищают информацию от неразборчивой чистки или размораживания уровней, который является всегда угрозой неграфической информации, сохраненной в data.
Используют новые поля (330-369 ссылки / указателя монопольного использования объекта, чтобы обслужить{*поддержать*} внутренние ссылки объекта базы данных. Произвольные значения метки полностью освобожденны от механики трансляции объекта ID. Это оппозиционно настроено в отношении 1005 xdata групп, которые оттранслированы в некоторых случаях, но не в других.
Остаются незатронутым 16КБ в объект xdata предел способности{*вместимости*}. Этот объект может также использоваться вместо xdata на определенных примитивах и объектах, если один так пожелания, с пониманием, что независимо от того, где Вы сохраняете xrecord объекты, они не имеют никакого встроенного предела размера, другого чем предел 2 ГБАЙТА, наложенных подписанным 32-разрядным целочисленным диапазоном.
В случае объектно - определенного состояния, xrecord объекты хорошо удовлетворены для сохранения больших количеств сохраненной информации, в то время как xdata лучше удовлетворенный для меньших количеств данных.
При монтаже иерархии xrecord объектов (добавление монопольного использования или ссылки указателя к объекту), тот объект должен уже существовать в базе данных, и, таким образом, иметь законное имя примитива. Поскольку acdbEntMake () не возвращает имя примитива, и acdbEntLast () только признает графические объекты, Вы должны использовать acdbEntMakeX () если Вы ссылаетесь на неграфические объекты.
AcdbEntMakeX () функция возвращает имя примитива объекта, добавленного к базе данных (или графический или неграфический). Начальный Выпуск 13 выполнения acdbEntMake () только поддержанные объекты, чей класс диктовал его определенный объект контейнера владельца в текущем рисунке (типа входов таблицы идентификаторов, весь снабженный Выпуск 13 типов примитива, и объекты словаря), и зарегистрировал новый объект с его владельцем. Эти функции продолжат делать это для того же самого набора встроенных объектных классов, включая примитивы. Для xrecords и всех классов пользователя, эти функции добавят объект к базе данных, оставляя это до приложения, чтобы установить его связи{*ссылки*} монопольных использований снова до словари имен объектов. AcdbEntMakeX () функция добавляет объект к базе данных для всех типов объекта, включая, которые идут С AutoCAD. Так, даже при использовании этой функции на существующих типах примитива, ваша программа ответствена за установку монопольного использования.
Xrecords
Xrecords дают возможность Вам добавить произвольные, специфические для приложения данные. Поскольку они - альтернатива к определению вашего собственного объектного класса, они особенно полезны для программистов AutoLISP. Xrecord - образец класса AcDbxrecord, который является подклассом AcDbObject. Xrecord государство{*состояние*} определен как содержание resbuf цепочки, которая является списком групп данных, каждая из которых в свою очередь содержит код группы DXF плюс связанные данные. Значение кода группы определяет связанный тип данных. Коды Группы для xrecords находятся в диапазоне от 1 до 369. Следующий раздел описывает доступную группу DXF коды.
Не имеется никакого свойственного предела размера на сумму данных, которые Вы можете сохранять в record. Xrecords может принадлежать любому другому объекту, включая словарь расширения{*продления*} любого объекта, словари имен объектов, любого другого словаря, или другого xrecords.
Никакое уведомление не послано, когда xrecord изменяется. Если приложение должно знать, когда объект, имеющий xrecord изменился, приложение будет должно послать его собственное уведомление.
AcDbXrecord класс обеспечивает две функции члена для установки и получения resbuf цепочками, setfromRbChain () и rbChain () функциями:
Acad::ErrorStatus
AcDbXrecord::setFromRbChain(
resbuf& pRb,
AcDbDatabase* auxDb=NULL);
Acad::ErrorStatus
AcDbXrecord::rbChain(
resbuf** ppRb,
AcDbDatabase* auxDb=NULL) const;
AcDbXrecord:: setFromRbChain() функция заменяет существующую resbuf цепочку .
Заданные по умолчанию действия
Имеется другой способ определить действия в дополнение к запросу ads_action_tile (). Вы можете определять заданное по умолчанию действие для полного диалогового окна, когда Вы вызываете ads_new_dialog (). Неперекрывающее расположение может иметь только единственное действие во времени. Если приложение определяет больше чем одно действие, они заменяют друг друга в следующем порядке очередности:
1 заданное по умолчанию действие, указанное ads_new_dialog () запрос (использовал только, если никакое действие не явно назначено на неперекрывающее расположение).
2 действие, назначенное последним ads_action_tile () запрос. Когда неперекрывающее расположение названо в больше чем одним ads_action_tile () запросом, только последним, такой запрос (до ads_start_dialog ()) имеет любой эффект (это подобно назначению множественных значений к той же самой переменной). PDB средство позволяет только одно действие в неперекрывающее расположение.
Заданный по умолчанию Класс для Расширения Протокола
Рекомендуется, чтобы Вы осуществили заданный по умолчанию класс расширения протокола, как показано в примере в конце этой главы. Если не имеется никакой соответствующий объект расширения протокола для специфического класса, ObjectARX исследования иерархия классов и использует самый близкий, который это находит. Также рекомендуется, чтобы Вы связали заданный по умолчанию класс расширения протокола с AcRxObject или с некоторым другим классом наверху ObjectARX иерархии классов типа AcDbEntity (в этом примере) или AcDbObject.
Загрузка ObjectARX Приложения
Вы можете загружать приложение ObjectARX, используя любой из следующих методов:
Обеспечивают приложение особенностями, которые позволяют этому быть запросом, загруженным в соответствии с AutoCAD. Эти особенности включают специфические для приложения входы в Windows NT (или Windows ® 95) системный реестр. См. “ Загрузка Запроса ” на странице 45.
Определяют приложение в начальном файле модуля, acad.rx. Этот файл содержит текст ASCII с именами всех программ AutoCAD, должен загрузиться, когда это начато. Каждая строка в файле содержит название программы (с путем, если файл не в каталоге на пути поиска файлов библиотеки AutoCAD). Acad.rx файл должен также быть в каталоге на пути поиска файлов AutoCAD.
Делают прикладной запрос загрузки от другого приложения ObjectARX, используя AcRxDynamicLinker:: loadModule ().
Используют диалоговое окно APPLOAD, определенное в премии AutoCAD, программируют loadapp.arx.
Используют arxload () функция от АвтоЛисп.
Используют acedArxLoad () функция от ObjectARX.
Вводят команду ARX в командную строку AutoCAD и используют опцию Load.
Загрузка по требованию
Требование, загружающее механизм - по существу тот же самый для приложения ObjectDBX, поскольку это - для ObjectARX-приложения. Единственное различие находится в том, где информация найдена в системном реестре. Для требования, загружающего ObjectARX-приложения, AutoCAD смотрит в системном реестре системы под следующим:
HKEY_LOCAL_MACHINE
Software
Autodesk
AutoCAD
R15.0
ACAD-xxxxxxx-xxxxxxxx
Applications
xxxxxxx-xxxxxxxx является номером, уникальным к каждой инсталляции.
Для требования загружающего приложения DBX, ObjectDBX будет смотреть в системном реестре системы под следующим:
HKEY_LOCAL_MACHINE
Software
Autodesk
ObjectDBX
R15.0
Applications
Они - жестко закодированные ключи и - тот же самый для любого приложения на любой машине. Ваша прикладная информация идет при входе Приложений.
Загрузка по запросу
Загрузка Запроса - особенность AutoCAD, который автоматически пытается загружать приложение ObjectARX, которое - не резидент в AutoCAD. Приложения ObjectARX могут быть предназначены для загрузки в соответствии с AutoCAD под одним или большим количеством следующих обстоятельств:
· когда читается чертежный файл, который содержит заказные объекты, созданные отсутствующим приложением;
· когда пользователь или другое приложение выпускает одну из команд отсутствующего приложения;
· когда AutoCAD начат;
ОБРАТИТЕ ВНИМАНИЕ На приложения, которые осуществляют загрузку запроса на запуске AutoCAD, будет загружен прежде, чем перечисляли в acad.rx.
AutoDesk рекомендует разработать приложения ObjectARX, которые воспользуются преимуществом загружающей запроса особенности AutoCAD потому что загрузка запроса, обеспечивая следующие выгоды:
· Ограничивает создание полномочных объектов (см. главу 14, “ Полномочные Объекты”)
· Обеспечивает большую гибкость для загрузки приложений ObjectARX
· Сохраняет память, загружая приложения только, когда их функциональные возможности требуются
Для приложения, чтобы быть доступный для загрузки запроса, специфическая для приложения информация должна присутствовать в системном реестре системы Windows. Кроме того, Приложения ObjectARX с больше чем один DLL могут нуждаться в модуле “контроллера”, который является ответственным за загрузку всех других компонентов
Приложение. Наконец, DEMANDLOAD системная переменная должна быть установлена в соответствующее значение для загрузки запроса.
ОБРАТИТЕ ВНИМАНИЕ, что приложение ObjectARX может быть запрос, загруженный от пути на местной машине, или, используя адрес Internet.
Загрузка Запроса на Команде
AutoCAD будет пытаться загружать соответствующее Приложение ObjectArx, если пользователь вызывает команду, которая не зарегистрирована с AutoCAD.
Чтобы поддерживать загрузку запроса на обращении команды, программа инсталляции приложения ObjectARX должна создать соответствующие клавиши{*ключи*} и значения в системном реестре для команд приложения. Раздел приложения Commands системного реестра должен содержать информацию команды подобно этому:
\\ HKEY_LOCAL_MACHINE\SOFTWARE\
Autodesk\ ...
...
PolySampInc\polysamp\
Loader\MODULE:REG_SZ:c:\polysampinc\arx\polyui.arx
Name\PolySamp:REG_SZ:PolyCad
Commands\
ASDKPOLY:REG_SZ:ASDKPOLY
ASDKDRAGPOLY:REG_SZ:ASDKDRAGPOLY
ASDKPOLYEDIT:REG_SZ:ASDKPOLYEDIT
Groups\
ASDK:REG_SZ:ASDK
...
В этом примере, зарегистрированный префикс разработчика разработчика (ASDK) используется как префикс для всех команд, чтобы гарантировать, что не будет иметься никакого возможного конфликта с командами того же самого названия{*имени*} в других приложениях.
Приложение ObjectArx должно также включить соответствующие запросы к acedRegCmds макрокоманде для загрузки запроса на команде, чтобы работать.
Загрузка Запроса на Обнаружении Заказных Объектов{*целей*}
Когда DWG или DXF файл, содержащий заказные объекты загружен, AutoCAD определяет, действительно ли приложение - обработчик загружено. Если приложение не загружено, и первый бит переменной системы DEMANDLOAD установлен, AutoCAD ищет системный реестр системы Windows информацию относительно приложения и его модуля загрузчика. Если AutoCAD находит соответствующую информацию в системном реестре, это загружает приложение.
ОБРАТИТЕ ВНИМАНИЕ, что загрузка Запроса на обнаружении заказных классов будет только работать с классами, которые получены из AcDbObject, или непосредственно или косвенно.
Как гипотетический пример, давайте предполагать, что AutoCAD читает файл, созданный Приложением ObjectArx polysamp (изделие{*программа*} PolySamp компании).
1 После чтения чертежного файла, AutoCAD сталкивается с заказными объектами{*целями*}, созданными с приложением polysamp, и решает, что приложение не загружено.
2 AutoCAD находит, что DEMANDLOAD системная переменная установлена, чтобы допустить загрузке запроса приложений на полномочном обнаружении, так что это ищет раздел Приложений AutoCAD системного реестра для polysamp клавиши{*ключа*}.
В пределах этой клавиши{*ключа*}, это находит значение LoadCtrls, которое определяет условия{*состояния*}, при которых приложение должно быть загружено, и значение RegPath, которое обеспечивает полный путь системного реестра для polysamp модуля. Этот раздел системного реестра смотрел бы кое-что вроде этого:
\\HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R15.0\
ACAD-1:409\
Applications\PolyCAD\
LoadCtrls:REG_DWORD:0xd
RegPath:REG_SZ:
\\HKEY_LOCAL_MACHINE\SOFTWARE\PolySampInc\polysamp
3 AutoCAD читает polysamp\Loader клавишу{*ключ*}, чтобы определить каталог, путь, и имя файла модуля, который будет загружен. Этот раздел каталога смотрел бы кое-что вроде этого:
\\ HKEY_LOCAL_MACHINE\SOFTWARE\
PolySampInc\polysamp\
Loader\MODULE:REG_SZ:c:\polysampinc\arx\polyui.arx
Name\PolySamp:REG_SZ:PolyCad
4 AutoCAD тогда пытается загружать ObjectARX модуль. Если загрузки модуля успешно, AutoCAD прибавляет маркер{*дескриптор*} приложения к списку прикладных маркеров{*дескрипторов*}, которые будут посланы kLoadDwgMsg сообщение. AutoCAD тогда подтверждает{*проверяет*}, что приложение было загружено должным образом, и подтверждает{*проверяет*}, что заказной класс зарегистрирован. Если приложение было загружено успешно, AutoCAD продолжится
Загружать чертежный файл. Если ObjectARX модуль не может быть загружен, или если все еще не имеется выполнения класса, доступные, заказные объекты{*цели*} обработаны как proxies, и загрузка продолжается.
Загрузка Запроса на Запуске AutoCAD
Загрузка Запроса Приложения ObjectArx на запуске AutoCAD может быть определена, используя 0x02 (или Вы можете исполнять ИЛИ 0x02 с другим законным значением) со значением LoadCtrls в системном реестре, как показано здесь.
\\HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R15.0\
ACAD-1:409\
Applications\PolyCAD\
LoadCtrls:REG_DWORD:0x02
RegPath:REG_SZ:
Управление Приложениями с Системным реестром
Как только системная информация системного реестра была создана для загрузки запроса, что та же самая информация может использоваться набором функций ObjectARX, чтобы загружать, разгрузить, и контролировать присутствие Приложений ObjectArx, независимых от загружающей запроса особенности. Параметр AppName, используемый первой двумя из этих функций - логическое прикладное название{*имя*}.
Следующие функции ObjectARX могут использоваться с зарегистрированными прикладными названиями{*именами*}:
Bool acrxLoadApp ("AppName")
Эта функция берет одиночный параметр, который представляет случай{*регистр*} -нечувствительное логическое название{*имя*} приложения, которое будет загружено. Функция возвратилась бы 0, если загрузка потерпела неудачу, или 1, если загрузка преуспевает.
Bool acrxUnloadApp ("AppName")
Эта функция берет одиночный параметр, который представляет случай{*регистр*} -нечувствительное логическое название{*имя*} приложения, которое было предварительно загружено. Функция возвращается 0, если разгруженные сбои, или 1, если это преуспевает.
Пусто *acrxLoadedApps ()
Эта функция возвращает массив строк как пустой *, содержа логическое прикладное название{*имя*} каждого приложения, которое в настоящее время загружено. Функциональные возвращения ПУСТОЙ УКАЗАТЕЛЬ, если никакие приложения не загружены. Это - ответственность вызывающей программы выпустить пространство{*пробел*}, распределенное для возвращенных строк.
Заказные режимы объектной привязки
ObjectARX
обеспечивает способность создать заказные режимы объектной привязки. Эти режимы позволяют приложениям связывать новые объектные поспешные точки и Автопоспешные линии выравнивания с заказными и существующими примитивами. Чтобы создавать заказной режим объектной привязки, Вы должны делать следующее:
§
Создают и регистрируют заказной режим объектной привязки.
§ Создают классы расширения протокола, чтобы исполнить входную обработку точки.
§ Создают заказной глиф.
Следующие секции обсуждают эти предметы более подробно.
Заказные Уведомления
Когда модификации совершены{*переданы*} на объекте, объект закрыт, который вызывает подзавершение () виртуальная функция AcDbObject. В перегрузке этой функции в вашем классе пользователя, Вы можете уведомлять другие, что Вы закрываетесь после модификации. Эти уведомления должны быть ваше заказное уведомление в форме заказных функций на вашем классе. Не используйте уведомления, обеспеченные на AcDbObjectReactor для этой цели.
Закрытие файла и Проверки Последовательности
Базовый класс AcDbXrefFileLock обеспечивается, чтобы обработать управление закрытия файла таблицы перекрестных ссылок. Его основная цель состоит в том, чтобы готовить блок таблицы перекрестных ссылок в рисунке для правки по месту, тем не менее, это может использоваться для других целей. Принимается, что эти методы файла таблицы перекрестных ссылок работают на текущем рисунке базы данных. AcdbXrefReload () функция глобальной переменной обрабатывает список объекта IDs отчета{*записи*} таблицы блока таблицы перекрестных ссылок для перезагрузки таблицы перекрестных ссылок. Принимается, что каждая таблица перекрестных ссылок блокирует ссылки{*справочники*} объекта ID отчета{*записи*} таблицы чертежный файл таблицы перекрестных ссылок, который может быть перезагружен к текущему рисунку. Это имеет те же самые функциональные возможности как команда подсистемы ТАБЛИЦЫ ПЕРЕКРЕСТНЫХ ССЫЛОК AutoCAD
Для Перезагрузки.
Запись Объекта в файл
Запись в файл Объекта обращается{*относится*} к конверсионному процессу между государством{*состоянием*} объекта и одиночной последовательностью данных, для целей типа сохранения этого на диске, копирование этого, или регистрации его государства{*состояния*} для операции отмены. Запись в файл из иногда называется, преобразовывая в последовательную форму.
Запись в файл объекта в - процесс превращения последовательности данных назад в объект, иногда называемый deserializing.
Запись в файл используется в нескольких контекстах в AutoCAD:
Запись и чтение DWG файлы (использует формат DWG)
Запись и чтение DXF файлы (использует формат DXF)
Сообщающий среди AutoCAD, AutoLISP, и ObjectARX (использует формат DXF)
регистрация Отмены и восстановление (использует формат DWG)
операции Copying типа ВСТАВКИ, ТАБЛИЦЫ ПЕРЕКРЕСТНЫХ ССЫЛОК, и КОПИИ (использует формат DWG)
Листание (использует формат DWG)
AcDbObject имеет две функции элемента для записи в файл из: dwgOut () и dxfOut (), и две функции элемента для записи в файл в: dwgIn () и dxfIn ().
Эти функции элемента прежде всего называются в соответствии с AutoCAD; запись в файл объекта почти никогда явно не управляется приложениями, которые используют базу данных.
Однако, если ваше приложение осуществляет новые классы объекта базы данных, вы будете нуждаться в более глубоком понимании объектной записи в файл. См. главу 12, “ Происходящий от AcDbObject. ”
Dwg- и dxf- префиксы указывают два существенно различных формата данных, первый типично используемый в письменной форме к и от DWG файлов, и второй прежде всего для DXF файлов и AutoLISP entget, entmake, и функций entmod. Первичное различие между двумя форматами - то, что для DWG регистраторов (объект, который записывает, данные к файлу), данные явно не отмечены.
DXF регистраторы, напротив, присоединяют код группы данных с каждым элементом данных в изданном формате данных (см. главу 12, “ Происходящий от AcDbObject ”).
Запись Обертки COM
Вы можете записывать класс обертки COM, чтобы добавить функциональные возможности выбора к ActiveX модели Автоматизации, или Вы можете выставлять{*подвергать*} заказные объекты или примитивы.
Запросы AutoCAD и функции Команды
Следующие функции AutoCAD не могут быть вызваны, в то время как диалоговое окно активно:
§ acedCommand ()
§ acedCmd ()
§ acedHelp ()
§ acedOsnap ()
Запросы AutoCAD и Команды
Функции, описанные в этом разделе обращаются к командам AutoCAD и услугам.
Жесткие Указатели
Жесткая ссылка указателя защищает объект от чистки. Например, объект содержит жесткую ссылку указателя к уровню. Поэтому, Вы не можете производить чистку уровня, который указан одним или большее количество объектов. Когда новая база данных выписана от существующего (например, в операции WBLOCK), все жесткие указатели скопированы в новую базу данных.
Другие примеры жестких ссылок указателя
§
объект лидера содержит жесткую ссылку указателя к стилю измерения.
§ текстовый объект содержит жесткую ссылку указателя к текстовому стилю.
§ объект измерения содержит жесткую ссылку{*справочники*} указателя к стилю измерения.
§ mline объект имеет жесткую ссылку указателя к mline стилю.
Жесткое Монопольное использование
Следующее - три примера жесткого монопольного использования:
§
объект базы данных - жесткий владелец его словаря расширения{*продления*}.
§ блочная таблица - жесткий владелец образцовых пространственных и бумажных пространственных блочных отчетов{*записей*} таблицы (но не другие блочные отчеты{*записи*} таблицы).
§ словари Расширений{*продления*} - жесткие владельцы их элементов.
Значение Уровня Базы данных
Следующий набор функций устанавливает и восстанавливает текущее значение уровня в базе данных:
Acad::ErrorStatus
AcDbDatabase::setClayer(AcDbObjectId);
AcDbObjectId AcDbDatabase::clayer() const;
Значения причины Повторного вызова
Код |
Символ |
Описание | |||
1 |
CBR_SELECT |
Пользователь выбрал неперекрывающее расположение. Это - значение для большинства неперекрывающих расположений действия. | |||
2 |
CBR_LOST_FOCUS |
Окна редактирования For, пользователь передвигались в другое неперекрывающее расположение, но не делали заключительный выбор. Если это - причина для повторного вызова окна редактирования, ваше приложение не должно модифицировать значение связанной переменной, но должно проверить законность значения в окне редактирования. | |||
3 |
CBR_DRAG |
Для слайдеров, пользователь изменил значение слайдера, перемещая индикатор (или эквивалент) но не делал заключительный выбор. Приложение не должно модифицировать значение связанной переменной, но должно модифицировать текст, который отображает состояние слайдера. | |||
4 |
CBR_DOUBLE_CLICK |
Эта причина повторного вызова всегда следует за CBR_SELECT. Это обычно означает “ передают предыдущему выбору.” Это не должно отменить предыдущий выбор; это может смущать и раздражать пользователя. Для списков или кнопок изображения, пользователь дважды нажал, чтобы делать заключительный выбор. Для кнопок изображения, пользователь дважды нажал на кнопке изображения. |
Значение двойного щелчка на списке или кнопке изображения - до вашего приложения. Если основная цель диалогового окна состоит в том, чтобы выбрать элемент списка, двойной щелчок должен делать выбор и затем выходить из диалогового окна (в этом случае, атрибут is_default list_box неперекрывающего расположения должен быть истинен). Если список - не первичное неперекрывающее расположение в диалоговом окне, то с двойным щелчком нужно обращаться с тем же самый как создание выбора (1, или CBR_SELECT). Списки, которые позволяют пользователю выбирать множественные элементы (multiple_select = истина;) не может поддерживать двойное нажатие.
Если основная цель диалогового окна состоит в том, чтобы выбрать кнопку изображения, одиночный щелчок должен выбрать кнопку, но иногда это лучше для одиночного щелчка (или перемещение клавиатуры) чтобы высветить кнопку и ENTER или двойной щелчок, чтобы выбрать это.
Пример обработки кнопки изображения одиночного щелчка - диалоговое окно AutoCAD Choose Hatch Pattern (вызванный от команды BHATCH). Пример кнопок изображения двойного щелчка - диалоговое окно AutoCAD Select Text Font (вызванный от опции Set Style на Текстовом подменю по умолчаниюа, рисуют опускающееся меню), который показывает список с текстовыми названиями стиля и кнопками изображения с эквивалентными текстовыми значками стиля. В этом диалоговом окне, одиночный щелчок или на кнопке изображения или элементе списка высвечивает, и текстовое имя стиля и значок, и двойной щелчок на любом делает выбор.
Значения Списка Обработки
Значение list_box поля ввода может содержать ведущие пробелы. Если Вы отыскиваете множественные элементы, не проверите значение как строковое сравнение. Преобразуйте это к целому числу сначала, используя atoi ().
Принимая, что список принимает только единственный выбор, следующие проверки фрагмента кода был ли третий список элемент отобран. (Убедитесь, что строка пуста первая, потому что atoi () возвращается 0 для пустой строки также как для строки “0”.) следующий пример использует значение, прошел в пакете повторного вызова:
if (*cpkt->value != EOS) {
if ((atoi(cpkt->value) == 2) {
// Process the third entry.
...
}
}
Значение всплывающего списка никогда не имеет ведущее пространство, так что Вы не должны преобразовать значение. Всплывающие списки не позволяют множественный выбор.
Если список поддерживает множественный выбор, ваша программа должна делать преобразование и шаг через множественные значения в строке значения. Следующий пример требует, чтобы Вы включили файл заголовка стандартной библиотеки для C string.h.
Кроме того, Вы должны назвать mk_list () функцией со значением потока поля списка, cpkt- >value, и указателем на первоначальный список. Ради простоты, сообщения об ошибках не учтены.
resbuf
*mk_list(char *local, struct resbuf *oldlist)
{
char spaceset[] = {’ ’, ’\t’, ’\n’}, item[TILE_STR_LIMIT];
int nitem, i;
struct resbuf *findrb; *usrlist, *scratch, *usrlast;
usrlist = usrlast = NULL;
while (item = strtok(local, spaceset) != NULL) {
nitem = atoi(item);
findrb = oldlist;
for (i=0; i<nitem; i++) {
findrb=findrb->rbnext;
}
if (usrlist == NULL) {/*AБ*/ /* First item */
if (scratch = acutNewRb(RTSTR) == NULL)
// Assume it’s a string.
return NULL;
if ((scratch->resval.rstring = malloc(strlen(findrb->resval.rstring))) == NULL)
return NULL;
strcpy(scratch->resval.rstring, findrb->resval.rstring);
usrlist = usrlast = scratch;
} else { /* Trailing items */
if (scratch = acutNewRb(findrb->restype) == NULL)
return NULL;
if ((scratch->resval.rstring =malloc(strlen(findrb->resval.rstring))) ==NULL)
return NULL;
strcpy(scratch->resval.rstring, findrb->resval.rstring);
usrlast->rbnext = scratch;
usrlast = scratch;
}
}
return usrlist;
}
Этот пример также работает для выродившегося случая единственного выбора.