ObjectARX
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to use a reactor to prevent CAD's modify command?

35 REPLIES 35
Reply
Message 1 of 36
lhydmr
1538 Views, 35 Replies

How to use a reactor to prevent CAD's modify command?

Hi,all

        I want to use a reactor(AcDbObjectReactor?) to prevent user from modifying the entities which I created,such as move,copy,del,and so on. In the openForModify call-back,and the modified() method,what command shoule I add? or any other method I should write?

 

thanks a lot~

 

35 REPLIES 35
Message 21 of 36
Alexander.Rivilis
in reply to: artc2


@artc2 wrote:

Unfortunately, there is no elegant solution to dealing with preventing editing of objects.  All of the ways to do it have their drawbacks.  You just have to decide which is the least problematic for each particular situation.

 

i wish I had a better answer, but I don't.  😞


Thanks for the honest answer!

 


@lhydmr wrote:

A good idea,But,a locked layer can be easily unlocked,How to prevent this layer from unlocking?


You can check status of this layer in AcApDocManagerReactor::documentLockModeChanged reactor and if layer is unlocked then lock it.

 

I hope that Art did not say that it is unacceptable. 🙂

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 22 of 36
owenwengerd
in reply to: lhydmr

If locked layers are not suitable for you, then reactors will not be suitable either (because they can be unloaded). Perhaps you should consider securing your content with CADVault instead.

--
Owen Wengerd
ManuSoft
Message 23 of 36
lhydmr
in reply to: Alexander.Rivilis

In the documentLockModeChanged function,I can't operate the layer,Maybe documentLockModeChanged is just used for document ,not for layer! Is there a function for layer manager in reactor?

 

examper:

void CCmdAcApDocManagerReactor::documentLockModeChanged(AcApDocument* unnamed,AcAp::DocLockMode myPreviousMode,
      AcAp::DocLockMode myCurrentMode,AcAp::DocLockMode currentMode,
      const char* pGlobalCmdName)
{
 AfxMessageBox("1");
 const char* layerName ;
 layerName = "LockedLayer";
 //CCreatElement *OBJ = new CCreatElement;
 //layerName = OBJ->NlayerName;

 // 获得当前图形的层表
 AcDbLayerTable *pLayerTbl;
 acdbHostApplicationServices()->workingDatabase() ->getLayerTable(pLayerTbl, AcDb::kForRead);
 AfxMessageBox("2");

 // 判断是否包含指定名称的层表记录
 if (!pLayerTbl->has(layerName))
 {
  AfxMessageBox("21");
  pLayerTbl->close();
  return;
 }
 AfxMessageBox("3");
 AcAxDocLock DocLock;

 // 获得指定层表记录的指针
 AcDbLayerTableRecord *pLayerTblRcd;
 pLayerTbl->getAt(layerName, pLayerTblRcd, AcDb::kForWrite);
 AfxMessageBox("4");
 //将图层锁定
 if (pLayerTblRcd->isLocked() == false)
 {
  AfxMessageBox("图层锁定");
  pLayerTblRcd->setIsLocked(true);
 }
 AfxMessageBox("5");

 pLayerTblRcd->close();
 pLayerTbl->close();
}

 

Between  AfxMessageBox("3") and AfxMessageBox("4") ,the function will be error!

Message 24 of 36
Alexander.Rivilis
in reply to: lhydmr

1. Remove line with:

AcAxDocLock DocLock;

2. Replace acdbHostApplicationServices()->workingDatabase() with unnamed->database()

3. Check code of error.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 25 of 36
lhydmr
in reply to: Alexander.Rivilis

Ask for help:

       In the AcApDocManagerReactor, I can't operate the layer for AcDb::kForWrite,There will be an error between AfxMessageBox("please lock the layer"); and  AfxMessageBox("lock successful");

 

void CCmdAcApDocManagerReactor::documentLockModeChanged(AcApDocument* unnamed,AcAp::DocLockMode myPreviousMode,
      AcAp::DocLockMode myCurrentMode,AcAp::DocLockMode currentMode,
      const char* pGlobalCmdName)
{
 Acad::ErrorStatus es;

 const char* layerName;
 layerName = "LockedLayer";

 AcDbLayerTable *pLayerTbl;
 unnamed->database() ->getLayerTable(pLayerTbl,AcDb::kForRead);

 if (!pLayerTbl->has(layerName))
 {
  pLayerTbl->close();
  return;
 }
 else
 {
  AcDbLayerTableRecord *pLayerTblRcd;
  if ((es = pLayerTbl->getAt(layerName, pLayerTblRcd, AcDb::kForRead , false))!= Acad::eOk)
  {
   CString str;
   str.Format(_T("The reason for error:%s"),acadErrorStatusText(es));
   AfxMessageBox(str);
   pLayerTblRcd->close();
   pLayerTbl->close();
   return;
  }
  else if ((pLayerTblRcd->isLocked())!=true)
  {
   AfxMessageBox("please lock the layer");
   pLayerTbl->getAt(layerName, pLayerTblRcd, AcDb::kForWrite , false); 
   pLayerTblRcd->setIsLocked(true);
   AfxMessageBox("lock successful");
  }
  pLayerTblRcd->close();
 }
 pLayerTbl->close();
}

Message 26 of 36

Hi,

 

Here is an alternate approach that you may try.

 

Refere to the Step 7 example of the ObjectARX training material :

http://usa.autodesk.com/adsk/servlet/index?id=1911627&siteID=123112

 

To prevent the entity from being moved, the sample code in that example resets the original position after the "commandended".

 

 



Balaji
Developer Technical Services
Autodesk Developer Network

Message 27 of 36
Balaji_Ram
in reply to: Balaji_Ram

Sorry, I replied to Alex.

 

My previous reply was meant for "lhydmr"

 



Balaji
Developer Technical Services
Autodesk Developer Network

Message 28 of 36
Alexander.Rivilis
in reply to: lhydmr

Change lines:

AfxMessageBox("please lock the layer");
pLayerTbl->getAt(layerName, pLayerTblRcd, AcDb::kForWrite , false); 
pLayerTblRcd->setIsLocked(true);
AfxMessageBox("lock successful");

 with:

AfxMessageBox("please lock the layer");
pLayerTblRcd->upgradeOpen(); // <-- !!!!
pLayerTblRcd->setIsLocked(true);
AfxMessageBox("lock successful");

 

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 29 of 36
lhydmr
in reply to: Alexander.Rivilis

pLayerTblRcd->upgradeOpen(); // <-- !!!!

I've tried this way,but,In the AcApDocManagerReactor,This operation  is failure, It's return value is unnormal~Any other ideas?

Message 30 of 36
lhydmr
in reply to: Balaji_Ram

Thanks,I will try it~

Message 31 of 36
Alexander.Rivilis
in reply to: lhydmr

This code was tested with AutoCAD 2013 but it have to work also with previous AutoCAD versions. It prevent layer with name in global variable layerName from unlocking by user:

 

void LockLayerReactor::documentLockModeChanged(AcApDocument * param2, 
  AcAp::DocLockMode myPreviousMode, AcAp::DocLockMode myCurrentMode, 
  AcAp::DocLockMode currentMode, const ACHAR * pGlobalCmdName)
{
  Acad::ErrorStatus es;
  AcApDocManagerReactor::documentLockModeChanged(param2, 
      myPreviousMode, myCurrentMode, currentMode, pGlobalCmdName) ;
  if (!(currentMode & AcAp::kNotLocked)) { // Check the possibility of modifying
    AcDbLayerTableRecordPointer pLayer(layerName,param2->database(),AcDb::kForRead);
    if ((es = pLayer.openStatus()) != Acad::eOk) {
      if (es != Acad::eKeyNotFound) {
         acutPrintf(_T("Error open layer: %s"), acadErrorStatusText(es));
      }
      return;
    }
    if (!pLayer->isLocked()) {
      if ((es = pLayer->upgradeOpen()) != Acad::eOk) {
        acutPrintf(_T("Error upgradeOpen layer: %s"), acadErrorStatusText(es));
        return;
      }
      pLayer->setIsLocked(true);
    }
  }
}

But this code can not disable changing entity layer...

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 32 of 36
lhydmr
in reply to: Alexander.Rivilis

       Thanks to Alexander.Rivilis.

       It  is Really a good way,At the same time,I really appreciate your enthusiasm to help and answer.

       I test your code in the version of  AUTOCAD2005,this way is correct, and indeed can lock my layer. But,there is a little dissatisfied with this way,If I click on the copy or move command and so on, the layer will be locked automatically,But,If I unlock that layer, then immediately use the mouse to drag the entity which is in the layer,the entity will be draged in this time,then the layer will be locked.

        I know the reason is that you used the if statement:if (!(currentMode & AcAp::kNotLocked)),when I use the mouse to drag the entity,The program did not enter the judgment statement in this time. so the layer will not be locked automatically in this time.

        As I did not use this if statement, this sentence "pLayer->upgradeOpen()" can't pass!

        Anyway, this is a good way, I will use this method.

Message 33 of 36
Alexander.Rivilis
in reply to: lhydmr


@lhydmr wrote:
... I test your code in the version of  AUTOCAD2005,this way is correct, and indeed can lock my layer...

Oh! AutoCAD 2005 now is a rarity. Smiley Wink

 


lhydmr wrote:

        Anyway, this is a good way, I will use this method.


So we can think that solution was found?

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 34 of 36
lhydmr
in reply to: Alexander.Rivilis

        Sorry,I have no good way to solve this problem, and now I'm doing some tests, if there is a good way, I will sent method to the forum.

Message 35 of 36
lhydmr
in reply to: Alexander.Rivilis

Balaji_Ram recommanded this method:

 Refere to the Step 7 example of the ObjectARX training material : http://usa.autodesk.com/adsk/servlet/index?id=1911627&siteID=123112

 

To be demonstrated,It is a good way to solve this problem,Use the AcDbObjectReactor,In the openForModify(),we get the object Id which will be modifyed,Then we use the AcEditorReactor,In the commandEnded(),we reopen the object by the objectId,and in the commandEnded(),we can open the entity for write,while we can't do this in the function of AcDbObjectReactor.In the commandEnded(),we can set the entity to the original state.

 

 

Message 36 of 36
Alexander.Rivilis
in reply to: lhydmr

There are many ways to change the entities when commandEnded not fired. For example, OPM (Properties palette) or lisp function and so on.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost