Я тут немного подумал и склоняюсь к мысли, что динамические блоки (тут сложно найти тонкую грань между динамическими и статическими блоками - свойство/метод isDynamicBlock не показатель) не могут быть анонимными.
чего это? именно на анонимных блоках и построена вся работа с динамическими блоками, если верить логике автодеска. когда динамический блок вставляется, ему дается имя как и у родительской BTR. Дальше, любое изменение динамики приводит к рождению анонимного блока, который описывает текущее положение динамики, но ссылается на родительский. В итоге, если блок подергать 10 раз, мы получаем 10 анонимных блоков, каждый из которых описывает какое-то изменение динамики (это то и позволяет делать откат Ctrl+Z). После переоткрытия чертежа все анонимные блоки, которые не используются просто вычищаются. Странно, не удобно, но реализовано именно так. В свете всего этого становится понятно, зачем придумали функцию acdbSetReferenced (вот только работает она странноватенько).
Если хочешь защитить свои блоки, разбей все блоки. Т.к. насколько помню, анонимные блоки легко переделать в обычные и использовать.
Да я ж и не спорю, поэтому и написал в первом посте слово защита в кавычках. Задача скорей не защитить, а сделать не удобным использование БЕЗ arx-ины, за которую нужно платить деньги
.
По поводу защиты блоков и чертежей в автодеске придерживаются мнения, что все мы живем в каммунзме и всё, что нарисовано - общественная собственность (если не ошибаюсь, в начале существования автокада была возможность ставить пароль на блоки. также была возможность закрывать паролем весь чертеж. парольной защиты блоков уже нет в 2005 автокаде, парольный вход не поддерживается в 2020. зато везде пихают цифровые подписи, которые служат чисто для поддержания на плаву организаций, их выдающих и не обладают никакими защитными свойствами). было б здорово написать свой кастомный объект на основе блока (а лучше BTR), увы - нельзя, ибо сами автодесковцы говорят, что работает криво, да и пару лет назад я честно пытался. статические блоки - работают, динамика - не поддерживается.
Конечно ты накосячил. Но чтоб понять в чем именно нужно детально смотреть чертеж и код.
С этим никаких проблем нет, вот код функции
void lockcur()
{
acutPrintf(_T("\n*Начало..."));
int count1 = 0;
//-> для начала пробежимся по BTR, сделаем все наши блоки анонимными
AcDbBlockTable* pBlockTable;
if (Acad::eOk == acdbCurDwg()->getSymbolTable(pBlockTable, AcDb::kForRead))
{
AcDbBlockTableIterator *pBlockTableIterator = NULL;
if (Acad::eOk == pBlockTable->newIterator(pBlockTableIterator, true))
{
for (; !pBlockTableIterator->done(); pBlockTableIterator->step())
{
AcDbObjectId eId;
ACHAR * szBuffer;
pBlockTableIterator->getRecordId(eId);
AcDbBlockTableRecordPointer pRec(eId, AcDb::kForRead);
if (Acad::eOk != pRec.openStatus()) continue;
pRec->getName(szBuffer);
CString realName = szBuffer;
acutDelString(szBuffer);
if (realName.Find(_T('*')) == -1 && realName.Find(_T('$')) == -1)
{
count1++;
if (Acad::eOk != pRec->upgradeOpen()) continue;
pRec->setName(_T("*U"));
pRec->downgradeOpen();
if (Acad::eOk != acdbSetReferenced(eId))
acutPrintf(_T("\nError acdbSetReferenced"));
AcDbObjectIdArray blkInserts; blkInserts.removeAll();
pRec->getBlockReferenceIds(blkInserts);
pRec->getName(szBuffer);
CString anonymouseName = szBuffer;
acutDelString(szBuffer);
acutPrintf(_T("\n%s : %s"), realName.GetString(), anonymouseName.GetString());
}
}
}
if (pBlockTableIterator != NULL) delete pBlockTableIterator;
pBlockTable->close();
}
acutPrintf(_T("\n*Обработано %d блоков"), count1);
count1 = 0;
acutPrintf(_T("\n*Проверка количества блоков в БД чертежа после анонимизации :) ..."));
if (Acad::eOk == acdbCurDwg()->getSymbolTable(pBlockTable, AcDb::kForRead))
{
AcDbBlockTableIterator *pBlockTableIterator = NULL;
if (Acad::eOk == pBlockTable->newIterator(pBlockTableIterator, true))
{
for (; !pBlockTableIterator->done(); pBlockTableIterator->step())
{
AcDbObjectId eId;
ACHAR * szBuffer;
pBlockTableIterator->getRecordId(eId);
AcDbBlockTableRecordPointer pRec(eId, AcDb::kForRead);
if (Acad::eOk != pRec.openStatus()) continue;
pRec->getName(szBuffer);
CString realName = szBuffer;
acutDelString(szBuffer);
if (realName.Find(_T("*U")) != -1)
{
count1++;
acutPrintf(_T("\n%d. %s"), count1, realName.GetString());
}
}
}
if (pBlockTableIterator != NULL) delete pBlockTableIterator;
pBlockTable->close();
}
CString filePath = curDoc()->fileName();
acutPrintf(_T("\nЗапись в файл: %s"), filePath.GetString());
if (Acad::eOk != acdbCurDwg()->saveAs(filePath.GetString(), true, AcDb::kDHL_1024))
{
acutPrintf(_T("\n*** Не смогла я записать файл, увы"));
}
//<-
count1 = 0;
acutPrintf(_T("\n*Проверка количества блоков в БД чертежа после сохранения..."));
if (Acad::eOk == acdbCurDwg()->getSymbolTable(pBlockTable, AcDb::kForRead))
{
AcDbBlockTableIterator *pBlockTableIterator = NULL;
if (Acad::eOk == pBlockTable->newIterator(pBlockTableIterator, true))
{
for (; !pBlockTableIterator->done(); pBlockTableIterator->step())
{
AcDbObjectId eId;
ACHAR * szBuffer;
pBlockTableIterator->getRecordId(eId);
AcDbBlockTableRecordPointer pRec(eId, AcDb::kForRead);
if (Acad::eOk != pRec.openStatus()) continue;
pRec->getName(szBuffer);
CString realName = szBuffer;
acutDelString(szBuffer);
if (realName.Find(_T("*U")) != -1)
{
count1++;
acutPrintf(_T("\n%d. %s"), count1, realName.GetString());
}
}
}
if (pBlockTableIterator != NULL) delete pBlockTableIterator;
pBlockTable->close();
}
}
Чертеж будет во вложениях. В чертеже 58 блоков с нормальными именами. Открываем чертеж, делаем его текущим. Запускаем команду, выполняющую функцию, написанную выше. В логе командной строки будет выведена информация о текущем состянии дел. Сразу идет сопоставление реального имени и анонимного. Потом еще один пробег по БД, с отображением всех анонимных BTR, потом сохранение чертежа и снова отображение всего, что осталось в БД после сохранения.
После этого чертеж нужно закрыть и открыть заново. И попытаться объяснить, почему вместо 58 блоков осталось 4 (вставок нет, использования в других блоках нет, а они остались). Функция acdbSetReferenced использовалась 58 раз, а видим 4 (если ей НЕ пользоваться, мы тожеж увидим те же 4 блока через ArxDbg или утилиты очистки чертежа, если что
)
А теперь взрыв мозга... Если всё это проделать БЕЗ физического открытия чертежа (пользуемся readDwgFile), то видно все 58 анонимных блоков. В этом случае не вызывается реактор dwgFileOpened, который судя по справке и удаляет не используемые блоки (которые призвана защитить функция acdbSetReferenced!!!). Вот правда если "анонимизировать" блоки БЕЗ функции acdbSetReferenced, то в процессе открытия через readDwgFile их тоже всего 4. Вот такой закрученный сюжет
, в котором вроде бы бесполезная функция с одной стороны оказывается очень даже нужной с другой )))))))))))
Понапрягать можно. Но (!!!) ты дожен всё для них подготовить
сейчас слегка занят, да и главное понять, во что тыкать носом. в общем обязательно все подготовлю, но не на этой неделе.