Тема: Как "заблокировать" модификацию слоя ?

Есть служебный слой (locked), как запретить его модификацию, чтоб нельзя было его разблокировать,удалить,и т.д. ??
Навесил на него AcDbObjectReactor::openedForModify() и что
сделать дальше, чтоб этот Modify не состоялся ?

Re: Как "заблокировать" модификацию слоя ?

> Sergei
Восстанавливай параметры слоя в командном реакторе commandEnded(), если для него вызван в объектном реакторе метод modified(), но не вызван cancelled() и modifyUndone().
А удалить слой, на котором есть хотя бы один примитив AutoCAD не позволит.

Re: Как "заблокировать" модификацию слоя ?

Когда используешь '_Layer для изменения свойств слоя, то да commandEnded() срабатывает, но как быть если пользователь в выпадающем списке слоев в редакторе, например, просто ткнет в "замочек" - слой разблокируется, а  commandEnded() в этом случае не срабатывает ?

Re: Как "заблокировать" модификацию слоя ?

> Sergei
Тогда в AcEdInputContextReactor::beginQuiescentState()

Re: Как "заблокировать" модификацию слоя ?

Ok, буду пробовать. Спасибо.

Re: Как "заблокировать" модификацию слоя ?

А еще вопрос вдогонку, как отловить, что прошла регенерация чертежа ? Вариант с
::commandWillStart("REGEN") не устраивает, ибо многие другие команды также могут запускать глобальную регенерацию.

Re: Как "заблокировать" модификацию слоя ?

> Sergei
Вообще-то другого способа я не знаю. Уточни зачем это тебе нужно - возможно есть другое решение.

Re: Как "заблокировать" модификацию слоя ?

запускается OpenedForModify смотрим, что за объект пришел.
если он AcDbLayerTableRecord *lTR=AcDbLayerTableRecord::cast(dbObj);
if (!lTRObj) значит не трогать.
а если наоборот, спросить имя.
если имя lTB->getName(lName); такое, какое нужно,
берем id и записываем в глобальную переменную, типа DocVars.docData().idLayer=lTB->id();
пользователь радуется - поменял настройки. но не тут то было!
идем в objectModified, сравниваем id того, что туда пришло с записанным id, если совпадает -  ставим триггер на запрет входа в OpenedForModify, получаем объект
AcDbObjectPointer <AcDbLayerTableRecord> *lTR(DocVars.docData().idLayer,AcDb::kForWrite)
меняем все настройки обратно, закрываем объект, снимаем триггер, выводим сообщения с ругательствами пользователю acedAlert("Не влезай - убьет!");
по моему, так. Завтра попробую накатать.

Re: Как "заблокировать" модификацию слоя ?

> Зигмус
Вообще-то в objectModified объект (слой) еще открыт. Так что не уверен, что такие манипуляции к чему-то хорошему приведут.

Re: Как "заблокировать" модификацию слоя ?

Sergei пишет:

А еще вопрос вдогонку, как отловить, что прошла регенерация чертежа ?

Вообще-то есть пара недокументированных функций:

int __stdcall acedRegenPending(void);
int __cdecl isRegenHappening(void);

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

Re: Как "заблокировать" модификацию слоя ?

Относительно необходимости поймать regen:
задача примерно такая-  стоят скажем рядом две вставки одного блока. Одну из них надо закрасить серым (затемнить), делаем ее как-бы временно недоступной, но она должна быть видима. А та вставка, что рядом - в своих родных цветах, ее можно редактировать. Я был вынужден красить все внутренности определения в серый цвет, потом перерисовывать все вставки. А затем возвращал родные цвета в определении и перерисовывал только "рабочую" вставку.
В результате все серые, одна яркая (что и требовалось), но естественно при первом же regen'е  вся серость слетает.
Да и еще, работаю с Arx2002.

Re: Как "заблокировать" модификацию слоя ?

> Александр
Ривилис
Действительно, второй раз открывать не нужно. Это я погорячился.
Вот что получилось:

void DbReactor::objectOpenedForModify(const AcDbDatabase * dwg, const AcDbObject * dbObj)
{
    if (DocVars.docData().DoNotStartModifyReactor==true)return;
    AcDbLayerTableRecord *lTR=AcDbLayerTableRecord::cast(dbObj);
    if (lTR)
        {
            char *lName="";
            lTR->getName(lName);
            string st1,st2;
            st2="mylayer";
            st1="";
            st1.append(lName);
            if (st1.compare(st2)==0)
                {
                    DocVars.docData().layerId=lTR->id();
                }
        }
return;
}
void DbReactor::objectModified(const AcDbDatabase * dwg, const AcDbObject * dbObj)
{
    if (DocVars.docData().DoNotStartModifyReactor==true)return;
    AcDbObjectId layId;
    layId=dbObj->id();
    if (layId==DocVars.docData().layerId)
        {    DocVars.docData().DoNotStartModifyReactor=true;
            AcDbLayerTableRecord *lTR=AcDbLayerTableRecord::cast(dbObj);
            if (lTR->isWriteEnabled()!=Adesk::kTrue) lTR->upgradeOpen();
            string st="mylayer";
            lTR->setName(st.c_str());
            if (lTR->isLocked()!=true) lTR->setIsLocked(true);
            lTR->downgradeOpen();
        }
    return;
}

Отслеживаем разблокирование и переименование слоя mylayer

Re: Как "заблокировать" модификацию слоя ?

Кстати, про глобальные переменки, как
правильно передавать данные между несколькими работающими задачами, скажем    между реакторами ? Если в Arx2002 ?
И чуть подробнее о DocVars.docData() ?
Пробовал через acedPutSym(), но неудобно особенно, когда какой-нибудь сложный массив.

Re: Как "заблокировать" модификацию слоя ?

> Sergei
1) Глобальные переменные ты можешь использовать самые обычные в C++. Если тебе нужно привязать переменные к открытым чертежам AutoCAD, то удобно пользоваться классом CDocData. Посмотри файлы StdAfx.h DocData.h DocData.cpp, которые генерируются ObjectARX Wizard. В описание класса CDocData ты можешь включить свои переменные, которые будут свои в каждом из открытых документов AutoCAD.
Но если тебе нужно, чтобы этими переменными можно было пользоваться из lisp-программ, то тогда нужно использовать acedPutSym() или писать свои функции (вызываемы из lisp) для получения этих значений.
P.S.: Я кстати так и не понял для какого AutoCAD ты пишешь. Ты написал Arx2002 - это имеется в виду ObjectARX 2002 и AutoCAD 2002 или речь идет о VS .NET 2002?

Re: Как "заблокировать" модификацию слоя ?

Именно связка ObjectARX 2002 и AutoCAD 2002.

Re: Как "заблокировать" модификацию слоя ?

Да, связку DbReactor::objectOpenedForModify() и
DbReactor::objectModified() прикрутил - именно то, что надо. Как только пытаешься разлочить слой - он тут же сам  лочится снова.

Re: Как "заблокировать" модификацию слоя ?

А для функций:
int __stdcall acedRegenPending(void);
int __cdecl isRegenHappening(void);
какой .lib нужен ?

Re: Как "заблокировать" модификацию слоя ?

> Sergei
acad.lib - но в AutoCAD 2002 их наверное нет. Сейчас проверить не могу - нет под рукой.

Re: Как "заблокировать" модификацию слоя ?

Видимо нет, подключил acad.lib, все равно не узнает.

Re: Как "заблокировать" модификацию слоя ?

Я проверил - acad.exe в 2002 версии их не экспортирует.

Re: Как "заблокировать" модификацию слоя ?

Sergei пишет:

Относительно необходимости поймать regen...

Мне кажется regen ловить совсем не надо.
При определении блока для всех его примитивов поставь цвет «ПоБлоку».
Если это сделано – то достаточно ставить нужный цвет для каждой конкретной вставки (blockReference), и при всех regen цвета вставок останутся без изменений.

Re: Как "заблокировать" модификацию слоя ?

Александр, а нельзя ли использовать какой-нибудь реактор (AcDbEntityReactor, AcDbObjectReactor или др.), чтобы узнать, что данный примитив только что перерисовался на экране?
Насколько я понимаю AcDbEntityReactor::modifiedGraphics() - это не то?

Re: Как "заблокировать" модификацию слоя ?

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