More Copying Issues - prevent copying to another document?

More Copying Issues - prevent copying to another document?

Kyudos
Advisor Advisor
668 Views
8 Replies
Message 1 of 9

More Copying Issues - prevent copying to another document?

Kyudos
Advisor
Advisor

I like being able to Ctrl+C / Ctrl+V my custom objects within a document, but pasting them into a different document has some underlying data merging problems I don't have time to solve just yet. So, is there a way to prevent my objects from being copied to another document without disabling Ctrl+C / Ctrl+V?

 

In a similar vein, can I keep my objects out of a WBLOCK command?

 

I suspect I'll have to disable wblock cloning and kill off copy/paste - but is there another way?

0 Likes
669 Views
8 Replies
Replies (8)
Message 2 of 9

Kyudos
Advisor
Advisor

Ok - so I had a go at disabling wblockclone for my objects. However, despite what the docs say, subWblockClone never gets called. All copy functions go through deep clone.

 

I can crudely veto in documentLockModeChanged, but when is subWblockClone supposed to come into effect?

0 Likes
Message 3 of 9

Kyudos
Advisor
Advisor

Further - I can veto WBLOCK in PICKFIRST mode, and I can detect selection of my objects in endSSGet in not PICKFIRST mode. But after selecting from the WBLOCK dialog, Autocad returns to the WBLOCK dialog. How do I cancel the command? And what about WBLOCK of the whole drawing? How do I stop that?

0 Likes
Message 4 of 9

Kyudos
Advisor
Advisor

I've tried various ways in AcEditorReactor::beginWblock to try and cancel out of the command but it seems impossible to stop.

 

So I'm left hoping there is a simpler way to stop my objects taking part in WBLOCK.

 

Should I just do nothing in the  wblock filer?

 

Anyone?

0 Likes
Message 5 of 9

moogalm
Autodesk Support
Autodesk Support

Hi,

 

Can you please try implementing AcRxEventReactor::beginWblockObjects , which gives an access to preset mapper, you can skip the objects from IdMapper to prevent from cloning.

 

In this blog I discussed about mapping relation during CopyPaste:

http://adndevblog.typepad.com/autocad/2016/05/mapping-relation-between-source-and-destination-object...

 

 

0 Likes
Message 6 of 9

Alexander.Rivilis
Mentor
Mentor

@moogalm

I'd like to remember about case 11923088 related to Copy/Paste mapping algorithm.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | 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

0 Likes
Message 7 of 9

Kyudos
Advisor
Advisor

Thanks for the reply. Until I have time to look deeper into this, I simply set some flags when COPYCLIP starts that allows me to veto PASTECLIP to a different document. Of course that won't help pasting between instances of ACAD.

 

What would you recommend in that situation? Is it possible to have Ctrl+C / Ctrl+V within a document, but disallow pasting in another instance? This is why I was trying to manipulate the clipboard (see my other posts). Ideally I'd like to know the source of the data on the clipboard at pasting time...

0 Likes
Message 8 of 9

Kyudos
Advisor
Advisor

The blog link seems to be dead too...but i can see the Google cached version

0 Likes
Message 9 of 9

moogalm
Autodesk Support
Autodesk Support

Hi sorry about that,

 

@Alexander.Rivilis found a issue with the code, until further investigation I have made blog to private mode.

 

Anyway you can have a look the code structure.

 

 

using namespace std;

static void closeOrDeleteDbObj(AcDbObject *pObj)
{ if (pObj->objectId().isNull()) delete pObj; else pObj->close(); }

template <class T> struct unique_db_ptr : public unique_ptr<T, void(*)(AcDbObject*)>
{ unique_db_ptr<T>(T*& t) : unique_ptr<T,void(*)(AcDbObject*)>(t, closeOrDeleteDbObj) { } };


static AcDbObjectId addToDb(AcDbEntity *pEnt, AcDbDatabase *pDb = nullptr)
{
    AcDbObjectId newEntId;

    if (nullptr == pEnt)
        return newEntId;
    if (nullptr == pDb)
        pDb = acdbHostApplicationServices()->workingDatabase();
    if (nullptr == pDb)
        return newEntId;

    unique_db_ptr<AcDbEntity> ent(pEnt);
    AcDbBlockTable *pBt;
    if (eOk != pDb->getBlockTable(pBt, kForRead))
        return newEntId;
    
    unique_db_ptr<AcDbBlockTable> bt(pBt);
    AcDbBlockTableRecord *pMs;
    if (eOk == pBt->getAt(ACDB_MODEL_SPACE, pMs, kForWrite))
        unique_db_ptr<AcDbBlockTableRecord>(pMs)->appendAcDbEntity(newEntId, pEnt);

    return newEntId;
}

/*Globals*/
typedef std::tuple<CString, CString, CString> _CopyTuples;
typedef std::tuple<CString, CString, CString> _PasteTuples;
std::vector <_CopyTuples> vCopy;
std::vector <_PasteTuples> vPaste;

/*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();
	}


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);
		}
		vCopy.clear();
		vPaste.clear();

	}

class AcEdReactor :public AcEditorReactor
	{
	/*To watch for _PASTECLIP*/
	void virtual otherInsert(AcDbDatabase* pTo, AcDbIdMapping& idMap, AcDbDatabase* pFrom)
		{
		CString str;
		_PasteTuples pasteClipEntities;
		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(pEnt));
					acutPrintf(_T("\n%s : Handle"),objToHandleStr(pEnt));
					acutPrintf(_T("\n%s : Key"),  intDbIdToStr(idPair.key().asOldId()));
					acutPrintf(_T("\n%s : Value"),intDbIdToStr(idPair.value().asOldId()));
					pasteClipEntities = std::make_tuple(objToHandleStr(pEnt),
						intDbIdToStr(idPair.key().asOldId()),
						intDbIdToStr(idPair.value().asOldId())
						);
					vPaste.push_back(pasteClipEntities);
					}

				}
			}
		}


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

		/*To Watch For _COPYCLIP*/
		CString str;
		_CopyTuples copyCLipEntities;
		AcDbIdPair idPair;
		AcDbIdMappingIter mapIter(idMap);
		for (mapIter.start(); !mapIter.done(); mapIter.next()) {
			if (mapIter.getMap(idPair))
				{

				if(idPair.isCloned())
					{
				AcDbSmartObjectPointer<AcDbEntity> pEnt(idPair.key(), AcDb::kForRead);
				if (pEnt != NULL && pEnt.openStatus() == Acad::eOk)
					{
					acutPrintf(_T("\n%s"),objToClassStr(pEnt));
					acutPrintf(_T("\n%s : Handle"),objToHandleStr(pEnt));
					acutPrintf(_T("\n%s : Key"),intDbIdToStr(idPair.key().asOldId()));
					acutPrintf(_T("\n%s : Value"),intDbIdToStr(idPair.value().asOldId()));

					copyCLipEntities = std::make_tuple(
						objToHandleStr(pEnt),
						intDbIdToStr(idPair.key().asOldId()),
						intDbIdToStr(idPair.value().asOldId())
						);
					vCopy.push_back(copyCLipEntities);

					}
					}

				}
			}
		}

	};

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;
	}

 

0 Likes