Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save MadhukarMoogala/980f7c1a2ddfb142d370df570a99f91b to your computer and use it in GitHub Desktop.
Save MadhukarMoogala/980f7c1a2ddfb142d370df570a99f91b to your computer and use it in GitHub Desktop.

By Madhukar Moogala

I have received following query from an ADN partner recently, which seems to be quiet interesting.

Question:I want to watch _copyclip and _pasteclip to modify some entities after they have been pasted to another drawing. How do I get a map of the original clipboard objects to the new objects that were pasted in a second drawing?

User is interested to know objects that object mapping between source and destination drawings which may help in executing additionally functionalities on items that being copied.

To achieve we need to watch for AcEditorReactor :: otherBlock while performing _copyclip operation and AcEditorReactor:: otherInsert while performing _pasteclip operation.

When _copyclip operation is performed on an item, item is cloned to temporary database and mapping relation is established between source and temp database. When _pasteclip operation is performed on same item, item is cloned from temporat datbase to destination database, mapping relation is maintained between temp and source database After COPY- PASTE mechanism is done, temp database gets destroyedThe value of Mapping pair of _copyclip operation becomes key of to mapping of _pasteclip operation. this tip will help us to achieve the said mapping relation.

Code:

class AcEdReactor : public AcEditorReactor

{

    /*To watch for _PASTECLIP*/

    void virtual otherInsert(AcDbDatabase* pTo, AcDbIdMapping& idMap, AcDbDatabase* pFrom)

    {

        CString str;

        AcDbIdPair idPair;

        AcDbIdMappingIter mapIter(idMap);

        for (mapIter.start(); !mapIter.done(); mapIter.next())

        {

            if (mapIter.getMap(idPair))

            {

                AcDbSmartObjectPointer<AcDbEntity> pEnt(idPair.value(), AcDb::kForRead);

                if (pEnt != NULL && pEnt.openStatus() == Acad::eOk)

                {

                    /*acutPrintf(_T("\n%s"),objToClassStr(pCircle));

  acutPrintf(_T("\n%s : Handle"),objToHandleStr(pCircle));

  acutPrintf(_T("\n%s : Key"),  intDbIdToStr(idPair.key().asOldId()));

  acutPrintf(_T("\n%s : Value"),intDbIdToStr(idPair.value().asOldId()));*/

  vPaste.push_back(_PasteTuples(objToHandleStr(pEnt),
 								intDbIdToStr(idPair.key().asOldId()),
		 						intDbIdToStr(idPair.value().asOldId())));
                }
            }
        }
    }

    void virtual otherWblock(AcDbDatabase* pTo, AcDbIdMapping& idMap, AcDbDatabase* pFrom)

    {

        /*To Watch For _COPYCLIP*/

        CString str;

        AcDbIdPair idPair;

        AcDbIdMappingIter mapIter(idMap);

        for (mapIter.start(); !mapIter.done(); mapIter.next()) {

            if (mapIter.getMap(idPair))

            {

                AcDbSmartObjectPointer<AcDbEntity> pEnt(idPair.value(), AcDb::kForRead);

                if (pEnt != NULL && pEnt.openStatus() == Acad::eOk)

                {

                    //acutPrintf(_T("\n%s"),objToClassStr(pCircle));

                    //acutPrintf(_T("\n%s : Handle"),objToHandleStr(pCircle));

                    //acutPrintf(_T("\n%s : Key"),intDbIdToStr(idPair.key().asOldId()));

                    //acutPrintf(_T("\n%s : Value"),intDbIdToStr(idPair.value().asOldId()));

                    vCopy.push_back(_CopyTuples(objToHandleStr(pEnt),

​ intDbIdToStr(idPair.key().asOldId()),

​ intDbIdToStr(idPair.value().asOldId())));
                }
            }
        }
    }
};

Add the reactor in AcRx::kInitAppMsg: and remove the reactor in AcRx::kUnloadAppMsg

static AcEdReactor* testReactor = NULL;

//**************************************************************

extern "C"

    AcRx::AppRetCode
    acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt)

//**************************************************************

{

    switch (msg)

    {

    case AcRx::kInitAppMsg:

        acrxDynamicLinker->unlockApplication(pkt);

        acrxDynamicLinker->registerAppMDIAware(pkt);

        testReactor = new AcEdReactor();

        acedEditor->addReactor(testReactor);

        acedRegCmds->addCommand(_T("TestCmd"), _T("MPL"), _T("MPL"), ACRX_CMD_TRANSPARENT, tupes);

        break;

    case AcRx::kUnloadAppMsg:

        acedRegCmds->removeGroup(_T("TestCmd"));

        acedEditor->removeReactor(testReactor);

        break;

    default:

        break;
    }

    return AcRx::kRetOK;
}

Now the Command method to get mapping relation, note I have used std:: tuples and std:: pairs container which are available in C++11

/*Globals*/

typedef std::tuple<CString, CString, CString> _CopyTuples;

typedef std::tuple<CString, CString, CString> _PasteTuples;

std::vector<_CopyTuples> vCopy;

std::vector<_PasteTuples> vPaste;

void tupes()

{

   typedef std::pair<CString, CString> _MapPairs;

   std::vector<_MapPairs> pairs;

   /*Get Mapping Relation*/

   acutPrintf(_T("*******Mapping Relation Between Handles of Source and Destination Objects*******"));

   auto iterA = vCopy.begin();

   auto iterB = vPaste.begin();

   int i = 0;

   while (iterA != vCopy.end() || iterB != vPaste.end())

       ​
       {

           ​ _CopyTuples t;

           ​ _PasteTuples p;

           ​ if (iterA != vCopy.end())

​
           {

               ​ t = vCopy.at(i);

               ​ ++iterA;

               ​
           }

           ​ if (iterB != vPaste.end())

​
           {

               ​ p = vPaste.at(i);

               ​ ++iterB;

               ​
           }

           ​ /*Check if Source item's Value is same as Destination Item's Key*/if (!std::get<2>(t).CompareNoCase(std::get<1>(p)))

​
           {

               ​ pairs.push_back(_MapPairs(std::get<0>(t), std::get<0>(p)));

               ​
           }

           ​ i++;

           ​
       }

   ​ for (_MapPairs p : pairs)

​
   {

       ​ acutPrintf(_T("\n%s <------------> %s"), p.first, p.second);

       ​
   }
}

Utilities

/*Utils*/
CString getObjectIdToStr(const AcDbObjectId& id)


{

     CString str = _T("");

     ads_name ent;

     acdbGetAdsName(ent, id);

     str.Format(_T("%lx"), ent[0]);

     return str;

    
}

CString objToHandleStr(const AcDbObject* obj)


{

     ASSERT(obj != NULL);

     AcDbHandle handle;

     obj->getAcDbHandle(handle);

     TCHAR tmpStr[256];

     handle.getIntoAsciiBuffer(tmpStr);

     CString str = tmpStr;

     return str;

    
}

CString intDbIdToStr(const Adesk::IntDbId intVal)


{

     CString str = _T("");

        \#if !defined(_WIN64) && !defined(_AC64)

 str.Format(_T("%d"), intVal);

        \#else

         str.Format(_T("%I64d"), intVal);

        \#endif

         return str;

    
}

CString booleanToStr(bool b)

{

     CString str = _T("");

     if (b)

 str = _T("True");

     else

         str
        = _T("False");

     return str;
}

CString objToClassStr(const AcRxObject* obj)

{

     ASSERT(obj != NULL);

     AcRxClass* rxClass = obj->isA();

     if (rxClass == NULL)
    {

         ASSERT(0);

         acedAlert(_T("AcRxObject class has not called rxInit()!"));

         return _T("*Unknown*");

        
    }

     return obj->isA()->name();
}
  

output_92psf3

Image of mapping relation”

MPL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment