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

eWasNotifying / AcDbObjectReactor

7 REPLIES 7
Reply
Message 1 of 8
Anonymous
1044 Views, 7 Replies

eWasNotifying / AcDbObjectReactor


 

i've created a AcDbObjectReactor to change the
attribute text of a block, every time

something is happening to the block.

 

the problem is, i can't change the attribute text,
bacuse the opning for write returns eWasNotifying

while i close the pointer.

 

how can i change the text in the
attribute?

 

regards

chris

 


color=#008080>
 


color=#008080>//-----------------------------------------------------------------------------


color=#000080>void
MarxCiCADKoteReaktor::modified(
color=#000080>const
AcDbObject* dbObj)
{

color=#000080>#ifdef
OARXWIZDEBUG
    acutPrintf
("\nOARXWIZDEBUG - MarxCiCADKoteReaktor::modified()
called."
);
#endif
color=#008080>// OARXWIZDEBUG


   
color=#008080>// TODO: implement this function.

   
if ( DocVars.docData ().m_editCommand == false
)
       
color=#000080>return
;

    DocVars.docData
().m_editCommand = false ;

    //
disable the object reactor

   
color=#008080>// (so the object reactor knows that we are changing the
object)

    DocVars.docData ().m_doConversion =
true ;

    //Bemassung bearbeiten
und aktualisieren

   
ChangeKoteText(dbObj);

}


color=#000080>void
MarxCiCADKoteReaktor::ChangeKoteText(
color=#000080>const
AcDbObject*
dbObj)
{
        AcDbBlockReference
*pInsert =AcDbBlockReference::cast (dbObj)
;
       
color=#000080>if
( !pInsert
)
           
color=#000080>return

;

           
CString
str;
           
GetAttributeString(pInsert,
str);

           
SetAttributeString(pInsert, "test" );
color=#008080>// insert text to the
attribute
                                                   

}

Acad::ErrorStatus
MarxCiCADKoteReaktor::GetAttributeString(AcDbBlockReference* pObj, CString
&str)
{
// Acad::ErrorStatus es;

AcDbObjectIterator *pIter = NULL;
pIter = pObj->attributeIterator();

assert(pIter);

for(pIter->start();
!pIter->done(); pIter->step())
    
{
      AcDbAttribute*
pAttrib;
      AcDbObjectId   attId =
pIter->objectId();

     
color=#000080>if
(pObj->openAttribute(pAttrib, attId,
AcDb::kForRead) ==
Acad::eOk)
         
{
           str =
pAttrib->textString();
          
pAttrib->close();
         
}
     }
delete
pIter;
return
Acad::eOk;
}


Acad::ErrorStatus
MarxCiCADKoteReaktor::SetAttributeString(AcDbBlockReference* pObj, CString
str)
{
Acad::ErrorStatus es;
AcDbObjectIterator *pIter = NULL;

pIter = pObj->attributeIterator();
assert(pIter);


color=#000080>for
(pIter->start(); !pIter->done();
pIter->step())
    
{
      AcDbAttribute*
pAttrib;
      AcDbObjectId   attId =
pIter->objectId();

     
color=#000080>if
(pObj->openAttribute(pAttrib, attId,
AcDb::kForWrite) ==
Acad::eOk)
         
{
          
pAttrib->setTextString(str);
          
pAttrib->close();  //HERE IS THE ERROR

size=2>eWasNotifying
 

         
}
     }
delete
pIter;
return
Acad::eOk;
}


7 REPLIES 7
Message 2 of 8
Anonymous
in reply to: Anonymous

You can store the ObjectId of the object being
modified and then process that object in the commandEnded callback of an editor
reactor. The technique is demonstrated in the final labl of the arxlabs in the
ObjectARX SDK.


--
Cheers,

 

Stephen Preston
Developer Technical
Services
Autodesk

href="http://adn.autodesk.com">http://adn.autodesk.com

 


style="PADDING-RIGHT: 0px; PADDING-LEFT: 5px; MARGIN-LEFT: 5px; BORDER-LEFT: #000000 2px solid; MARGIN-RIGHT: 0px">


 

i've created a AcDbObjectReactor to change the
attribute text of a block, every time

something is happening to the block.

 

the problem is, i can't change the attribute
text, bacuse the opning for write returns eWasNotifying

while i close the pointer.

 

how can i change the text in the
attribute?

 

regards

chris

 


color=#008080>
 


color=#008080>//-----------------------------------------------------------------------------


color=#000080>void
MarxCiCADKoteReaktor::modified(
color=#000080>const
AcDbObject* dbObj)
{

color=#000080>#ifdef
OARXWIZDEBUG
    acutPrintf
("\nOARXWIZDEBUG - MarxCiCADKoteReaktor::modified()
called."
);
#endif
color=#008080>// OARXWIZDEBUG


   
color=#008080>// TODO: implement this
function.

   
color=#000080>if
( DocVars.docData ().m_editCommand == false
)
       
color=#000080>return
;

    DocVars.docData
().m_editCommand = false ;

    //
disable the object reactor

   
color=#008080>// (so the object reactor knows that we are changing the
object)

    DocVars.docData ().m_doConversion =
true ;

    //Bemassung bearbeiten
und aktualisieren

   
ChangeKoteText(dbObj);

}


color=#000080>void

MarxCiCADKoteReaktor::ChangeKoteText(const
AcDbObject* dbObj)
{
       
AcDbBlockReference *pInsert =AcDbBlockReference::cast (dbObj)
;
       
color=#000080>if
( !pInsert
)
           
return
;

           
CString
str;
           
GetAttributeString(pInsert,
str);

           
SetAttributeString(pInsert, "test" );
color=#008080>// insert text to the
attribute
                                                   

}

Acad::ErrorStatus
MarxCiCADKoteReaktor::GetAttributeString(AcDbBlockReference* pObj, CString
&str)
{
// Acad::ErrorStatus
es;

AcDbObjectIterator *pIter = NULL;
pIter =
pObj->attributeIterator();
assert(pIter);


color=#000080>for
(pIter->start(); !pIter->done();
pIter->step())
    
{
      AcDbAttribute*
pAttrib;
      AcDbObjectId   attId =
pIter->objectId();

     
color=#000080>if
(pObj->openAttribute(pAttrib, attId,
AcDb::kForRead) ==
Acad::eOk)
         
{
           str =
pAttrib->textString();
          
pAttrib->close();
         
}
     }
delete
pIter;
return
Acad::eOk;
}


Acad::ErrorStatus
MarxCiCADKoteReaktor::SetAttributeString(AcDbBlockReference* pObj, CString
str)
{
Acad::ErrorStatus es;
AcDbObjectIterator *pIter =
NULL;
pIter =
pObj->attributeIterator();
assert(pIter);


color=#000080>for
(pIter->start(); !pIter->done();
pIter->step())
    
{
      AcDbAttribute*
pAttrib;
      AcDbObjectId   attId =
pIter->objectId();

     
color=#000080>if
(pObj->openAttribute(pAttrib, attId,
AcDb::kForWrite) ==
Acad::eOk)
         
{
          
pAttrib->setTextString(str);
          
pAttrib->close();  //HERE IS THE ERROR

size=2>eWasNotifying
 

         
}
     }
delete
pIter;
return
Acad::eOk;
}


Message 3 of 8
Anonymous
in reply to: Anonymous

hey,

 

i tryed this! it works.

 

thanks.

 

regards

chris


style="PADDING-RIGHT: 0px; PADDING-LEFT: 5px; MARGIN-LEFT: 5px; BORDER-LEFT: #000000 2px solid; MARGIN-RIGHT: 0px">

You can store the ObjectId of the object being
modified and then process that object in the commandEnded callback of an
editor reactor. The technique is demonstrated in the final labl of the arxlabs
in the ObjectARX SDK.


--
Cheers,

 

Stephen Preston
Developer Technical
Services
Autodesk

href="http://adn.autodesk.com">http://adn.autodesk.com

 


style="PADDING-RIGHT: 0px; PADDING-LEFT: 5px; MARGIN-LEFT: 5px; BORDER-LEFT: #000000 2px solid; MARGIN-RIGHT: 0px">


 

i've created a AcDbObjectReactor to change the
attribute text of a block, every time

something is happening to the
block.

 

the problem is, i can't change the attribute
text, bacuse the opning for write returns eWasNotifying

while i close the pointer.

 

how can i change the text in the
attribute?

 

regards

chris

 


color=#008080>
 


color=#008080>//-----------------------------------------------------------------------------


color=#000080>void
MarxCiCADKoteReaktor::modified(
color=#000080>const
AcDbObject* dbObj)
{

color=#000080>#ifdef
OARXWIZDEBUG
   
acutPrintf ("\nOARXWIZDEBUG -
MarxCiCADKoteReaktor::modified() called."
);

color=#000080>#endif
//
OARXWIZDEBUG


    //
TODO: implement this function.

   
color=#000080>if
( DocVars.docData ().m_editCommand == false
)
       
color=#000080>return
;

    DocVars.docData
().m_editCommand = false ;

   
color=#008080>// disable the object reactor

   
// (so the object reactor knows that we are changing
the object)

    DocVars.docData
().m_doConversion = true ;

   
color=#008080>//Bemassung bearbeiten und
aktualisieren

   
ChangeKoteText(dbObj);

}


color=#000080>void

MarxCiCADKoteReaktor::ChangeKoteText(const
AcDbObject* dbObj)
{
       
AcDbBlockReference *pInsert =AcDbBlockReference::cast (dbObj)
;
       
color=#000080>if
( !pInsert
)
           
return
;

           
CString
str;
           
GetAttributeString(pInsert,
str);

           
SetAttributeString(pInsert, "test" );
color=#008080>// insert text to the
attribute
                                                   

}

Acad::ErrorStatus
MarxCiCADKoteReaktor::GetAttributeString(AcDbBlockReference* pObj, CString
&str)
{
// Acad::ErrorStatus
es;

AcDbObjectIterator *pIter = NULL;
pIter =
pObj->attributeIterator();
assert(pIter);


color=#000080>for
(pIter->start(); !pIter->done();
pIter->step())
    
{
      AcDbAttribute*
pAttrib;
      AcDbObjectId   attId =
pIter->objectId();

     
color=#000080>if
(pObj->openAttribute(pAttrib, attId,
AcDb::kForRead) ==
Acad::eOk)
         
{
           str =
pAttrib->textString();
          
pAttrib->close();
         
}
     }
delete
pIter;
return
Acad::eOk;
}


Acad::ErrorStatus
MarxCiCADKoteReaktor::SetAttributeString(AcDbBlockReference* pObj, CString
str)
{
Acad::ErrorStatus es;
AcDbObjectIterator *pIter =
NULL;
pIter =
pObj->attributeIterator();
assert(pIter);


color=#000080>for
(pIter->start(); !pIter->done();
pIter->step())
    
{
      AcDbAttribute*
pAttrib;
      AcDbObjectId   attId =
pIter->objectId();

     
color=#000080>if
(pObj->openAttribute(pAttrib, attId,
AcDb::kForWrite) ==
Acad::eOk)
         
{
          
pAttrib->setTextString(str);
          
pAttrib->close();  //HERE IS THE ERROR

size=2>eWasNotifying
 

         
}
     }
delete
pIter;
return
Acad::eOk;
}


Message 4 of 8
dba78
in reply to: Anonymous

Hello Stephen,

 

I'm facing a similar situation, except I do not run a command I could catch the end of.

I have a blockreference, showing a Height Cote as MText in it (I know, there could be an field-attribute bound to a BlockPoint, this is not an option in my case;  for my needs there is a 1:1 relationship between Bref and Bdef).

 

My goal is,  when the user changes the Z-Coordinate of the blockref via the Property-Panel , the heigthcotes shall be updated, and by changing the rotation, the text readability shall be maintained ( cos(rotation)>=0 --> normal, else rotated by 180deg).

 

I'm looking for an event/overrule to achieve this. Unfortunatelly all events leave the Object in notifying state before enter the handler.

 

For Stretch_editing there is a command I can catch, I only struggle with changing the props themselves. 

I found a DBObjectMonitor (not sure the source anymore) erlaier, which works fine to dump the info to the editor, but cannot be used for editing objects (I know, it's general not a good idea to modify object within an eventhandler - haven't found any better way), since the object is still notifying.

 

Somehow the ent.UpdgradeFromNotify doesn't seem to work here...

 

Recently I tried to add a bref.Modified event to my blockrefs when they are selected and used this handler

 

    Friend Sub CallBack_Object_Modified(sender As Object, e As EventArgs)
        Dim s As BlockReference = TryCast(sender, BlockReference)
        If s Is Nothing Then Return
        Try           
            s.UpgradeFromNotify() '<--  throws "ewasnotifying"
                    'do my BlockUpdate here
            s.DowngradeToNotify(True)
        Catch ex As Exception
        End Try

    End Sub

 

 

Any hints appreciated!

Best Regards,

Daniel

 

Acad Architecture 2012 x64 / Win7 pro x64/ .net 4.0 / VS2010

Message 5 of 8
loic.jourdan
in reply to: dba78

Hi,

Another solution is described here which might match your requirements: you can store the modified object oid and wait until AcDbObject::objectClosed(AcDbObjectId) is called.

 

"

[...stuff about AcDbSmartObjectPointer class...]

eWasNotifying Returned when the specified object is currently closing from kForWrite mode, is sending notification and kForWrite mode is requested again. At that point undo recording has been done, and all reactors get to see the same object state. The workaround for this status is to record that the notification happened then wait until the AcDbObject::objectClosed(AcDbObjectId) callback is made, at which point the object can be opened for write.

"

 

Since I'm not comfortable with VB, I may let you guess what corresponding code is.

 

I hope this helps

----
20-20 CAD / 20-20 Technologies
Message 6 of 8
dba78
in reply to: loic.jourdan

Hi,

 

thank you for the quick answer. 

In my understanding this would mean to catch the ObjectClosed event. 

 

After trying this it seems, the object is still notifying at the time the event is firing.

 

The current way is:

selecting the object -> adding the bref.objectClosed Eventhandler

changing the prop -> Event fires, Eventhandler is called

I alter the BlocktableRecord the bref belongs to -> OK

I need the Blockref to recordgraphicsmodified, to avoid a regen of the drawing (in a huge drawing I don't want to regen all entities...), therefore

I start a new transaction and open the Blockreference for write and at this point the "eWasNotifying" error throws.

 

I must be missing something..... 😞

With all these ObjectEvents I can only dump some info to the editor, or collect objectids????

Again, I have no Command to catch... 😞

I tried an Objectoverrule by overriding the Close method also -> invalid state....

 

I guess there MUST be a way to catch the very moment, when the object is available again for editing.... even in .net

 

BR,

Daniel

 

 

 

Message 7 of 8
loic.jourdan
in reply to: dba78

Hi,

Indeed, the workaround described seems not to work, sorry. As clearly described in the documentation: "[..objectClosed handler documentation...] Reopening the object for write is not supported since it leads to recursive notifications. Doing so will return Acad::eWasNotifying during the open operation."

 

So, I would try to record oid of modified object in your "CallBack_Object_Modified" and, instead of catching the end of any command (as described in this post), I would catch "DocumentLockModeWillChange" testing when the document is getting unlocked, this should be a good place to update your object.

 

I hope this helps.

----
20-20 CAD / 20-20 Technologies
Message 8 of 8
dba78
in reply to: loic.jourdan

Hi Loic,
thanks for the hint, will give this a try a post a feedback.
BR,
Daniel

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

Post to forums  

Autodesk Design & Make Report

”Boost