问题描述
问候专家社区,我正在尝试同步 AutoCAD 模型的两个窗口中的移动和缩放,即在两个不同的平面中打开 .dwg 分为两个窗口,一个活动的和另一个不活动的同步缩放(滚动 +或 -) 或从活动窗口到非活动窗口的移动 (PAN)(在 AutoCAD M3D 中具有两个开放平面的模型中 -> SYSWINDOWS :: tile Vertical),我正在研究,我发现此代码可以执行我想要的操作,但是只有一个平面,问题是我不能让它在 VS2019 c++ 中工作,我在带有“WinCallBack”的行中得到一个错误,表明 BOOL 不能成为一个常量,我提前感谢你的帮助。
#include "StdAfx.h"
#include "resource.h"
#pragma warning( disable : 4278 )
#include <windows.h>
#include <stdio.h>
#include "acedCmdNF.h"
#include "AcMyEditorReactor.h"
#include "AcMyInputContextReactor.h"
// Viewchanged notification is not received during a pan or zoom using mouse wheel.
// So identify those using WM messages.
BOOL WinCallBack(MSG *pMsg)
{
if( pMsg->message == WM_VSCROLL ||
pMsg->message == WM_HSCROLL ||
pMsg->message == WM_MOUSEWHEEL ||
pMsg->message == WM_MBUTTONUP)
{
// Sync the modelspace viewports
acDocManager->sendStringToExecute(acDocManager->mdiActiveDocument(),ACRX_T("SyncVTR "),false,true,false);
}
return FALSE;
}
class CMyTest1App : public AcRxArxApp
{
private:
AcMyEditorReactor *pEditorReactor;
AcMyInputContextReactor *pInputContextReactor;
public:
CMyTest1App () : AcRxArxApp ()
{
}
virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt)
{
AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;
// Editor reactor to receive to ViewChanged notification
pEditorReactor = new AcMyEditorReactor(true);
// InputContext reactor to receive quiescent state change notification
pInputContextReactor = new AcMyInputContextReactor();
// Viewchanged notification is not received during a pan or zoom using mouse wheel.
// So identify those using WM messages.
acedRegisterFilterWinMsg(WinCallBack);
return (retCode);
}
virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt)
{
AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;
// cleanup
if(pEditorReactor)
{
delete pEditorReactor;
pEditorReactor = NULL;
}
if(pInputContextReactor)
{
delete pInputContextReactor;
pInputContextReactor = NULL;
}
acedRemoveFilterWinMsg(WinCallBack);
return (retCode);
}
virtual AcRx::AppRetCode On_kLoadDwgMsg (void *pkt)
{
AcRx::AppRetCode retCode =AcRxArxApp::On_kLoadDwgMsg (pkt) ;
return (retCode) ;
}
virtual void RegisterServerComponents ()
{
}
// Command to sync the model space viewport parameters
static void AdskMyTestSyncVTR()
{
// Get the VTR updated
acedVports2VportTableRecords();
// We will update the other VTR only if view parameters change
Adesk::Boolean updateNeeded = Adesk::kFalse;
Acad::ErrorStatus es;
AcDbDatabase *pDb = acdbHostapplicationservices()->workingDatabase();
AcApDocument *pDoc = acDocManager->document(pDb);
if( pDoc == NULL )
return;
es = acDocManager->lockDocument(pDoc);
// This code at present can only deal with 2 Modelspace viewports split vertically in half
if(pDb->tilemode() == Adesk::kFalse)
{
struct resbuf rb;
if(ads_getvar(_T("cvport"),&rb) != RTnorM)
{
acutPrintf(_T("\nError using ads_getvar().\n"));
return;
}
if(rb.resval.rint == 1)
{
return; // Can only work with model space viewports.
}
}
AcDbViewportTable *pVT = NULL;
pDb->getViewportTable(pVT,AcDb::kForRead);
// Identify the left and right modelspace viewports
AcDbViewportTableRecord *pLeftVTR = NULL;
AcDbViewportTableRecord *pRightVTR = NULL;
AcDbViewportTableIterator *pIter = NULL;
es = pVT->newIterator(pIter);
if(es == Acad::eOk)
{
for (;!pIter->done();pIter->step())
{
AcDbViewportTableRecord *pVTR = NULL;
es = pIter->getRecord(pVTR,AcDb::kForRead);
if(es == Acad::eOk)
{
AcGePoint2d ll = pVTR->lowerLeftCorner();
AcGePoint2d ur = pVTR->upperRightCorner();
if(ll.isEqualTo(AcGePoint2d(0,0)))
{// Left modelspace viewport
pLeftVTR = pVTR;
}
else if(ur.isEqualTo(AcGePoint2d(1.0,1.0)))
{// Right modelspace viewport
pRightVTR = pVTR;
}
else
pVTR->close();
}
}
// If for some reason,we did not have two modelspace viewports,// lets stop here.
if(pLeftVTR == NULL)
{
if(pRightVTR != NULL)
pRightVTR->close();
return;
}
if(pRightVTR == NULL)
{
if(pLeftVTR != NULL)
pLeftVTR->close();
return;
}
// Ensure that the two viewports are split vertically in half.
// If not,the view parameters when applied from one to another
// may not apply directly using this code.
// If the viewports were resized manually,set them right.
AcGePoint2d ll1 = pLeftVTR->lowerLeftCorner();
AcGePoint2d ur1 = pLeftVTR->upperRightCorner();
AcGePoint2d ll2 = pRightVTR->lowerLeftCorner();
AcGePoint2d ur2 = pRightVTR->upperRightCorner();
if(ll1.isEqualTo(AcGePoint2d(0.0,0.0)) == false)
{
if(! pLeftVTR->isWriteEnabled())
pLeftVTR->upgradeopen();
pLeftVTR->setLowerLeftCorner(AcGePoint2d(0.0,0.0));
}
if(ur1.isEqualTo(AcGePoint2d(0.5,1.0)) == false)
{
if(! pLeftVTR->isWriteEnabled())
pLeftVTR->upgradeopen();
pLeftVTR->setUpperRightCorner(AcGePoint2d(0.5,1.0));
}
if(ll2.isEqualTo(AcGePoint2d(0.5,0.0)) == false)
{
if(! pRightVTR->isWriteEnabled())
pRightVTR->upgradeopen();
pRightVTR->setLowerLeftCorner(AcGePoint2d(0.5,0.0));
}
if(ur2.isEqualTo(AcGePoint2d(1.0,1.0)) == false)
{
if(! pRightVTR->isWriteEnabled())
pRightVTR->upgradeopen();
pRightVTR->setUpperRightCorner(AcGePoint2d(1.0,1.0));
}
// Get the active model space viewport
struct resbuf res;
acedGetvar(L"CVPORT",&res);
short vpnumber = res.resval.rint;
// Identify the model space viewports from/to which settings will be copied
// The active modelspace viewport is the viewport from which settings will be copied
AcDbViewportTableRecord *pFromVTR = NULL;
AcDbViewportTableRecord *pToVTR = NULL;
if(pLeftVTR->number() == vpnumber)
{
pFromVTR = pLeftVTR;
pToVTR = pRightVTR;
}
if(pRightVTR->number() == vpnumber)
{
pFromVTR = pRightVTR;
pToVTR = pLeftVTR;
}
// Sorry,we did not identify the active viewport
// from which settings need to be copied.
if(pFromVTR == NULL || pToVTR == NULL)
return;
// copy the VTR settings from one modelspace viewport to another
// only if they are different. We will use a tolerance to ensure
// very small differences do not get us in a soup. I meant loop :)
AcGetol newTol;
newTol.setEqualPoint (0.00001);
newTol.setEqualVector(0.00001);
// ViewDirection
AcGeVector3d fromViewDir = pFromVTR->viewDirection();
AcGeVector3d toViewDir = pToVTR->viewDirection();
if(pFromVTR->viewDirection().isEqualTo(pToVTR->viewDirection(),newTol) == false)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeopen();
pToVTR->setViewDirection(pFromVTR->viewDirection());
updateNeeded = Adesk::kTrue;
}
// ViewTwist
if(abs(pFromVTR->viewTwist() - pToVTR->viewTwist()) > 0.01)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeopen();
pToVTR->setViewTwist(pFromVTR->viewTwist());
updateNeeded = Adesk::kTrue;
}
// Target
if(pFromVTR->target().isEqualTo(pToVTR->target(),newTol) == false)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeopen();
pToVTR->setTarget(pFromVTR->target());
updateNeeded = Adesk::kTrue;
}
// BackClipEnabled
if(pFromVTR->backClipEnabled() != pToVTR->backClipEnabled())
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeopen();
pToVTR->setBackClipEnabled(pFromVTR->backClipEnabled());
updateNeeded = Adesk::kTrue;
}
// BackClipdistance
if(abs(pFromVTR->backClipdistance() - pToVTR->backClipdistance()) > 0.01)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeopen();
pToVTR->setBackClipdistance(pFromVTR->backClipdistance());
updateNeeded = Adesk::kTrue;
}
// FrontClipEnabled
if(pFromVTR->frontClipEnabled() != pToVTR->frontClipEnabled())
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeopen();
pToVTR->setFrontClipEnabled(pFromVTR->frontClipEnabled());
updateNeeded = Adesk::kTrue;
}
// FrontClipdistance
if(abs(pFromVTR->frontClipdistance() - pToVTR->frontClipdistance()) > 0.01)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeopen();
pToVTR->setFrontClipdistance(pFromVTR->frontClipdistance());
updateNeeded = Adesk::kTrue;
}
// Elevation
if(abs(pFromVTR->elevation() - pToVTR->elevation()) > 0.01)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeopen();
pToVTR->setElevation(pFromVTR->elevation());
updateNeeded = Adesk::kTrue;
}
// centerPoint
if(pFromVTR->centerPoint().isEqualTo(pToVTR->centerPoint(),newTol) == false)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeopen();
pToVTR->setCenterPoint(pFromVTR->centerPoint());
updateNeeded = Adesk::kTrue;
}
// Height
if(abs(pFromVTR->height() - pToVTR->height()) > 0.01)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeopen();
pToVTR->setHeight(pFromVTR->height());
updateNeeded = Adesk::kTrue;
}
// Width
if(abs(pFromVTR->width() - pToVTR->width()) > 0.01)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeopen();
pToVTR->setWidth(pFromVTR->width());
updateNeeded = Adesk::kTrue;
}
// Done with the VTR
pLeftVTR->close();
pRightVTR->close();
delete pIter;
}
es = pVT->close();
es = acDocManager->unlockDocument(pDoc);
// Update the Vports if we did change any of the VTR parameters
if(updateNeeded)
{
acedVportTableRecords2Vports();
}
}
};
//-----------------------------------------------------------------------------
IMPLEMENT_ARX_ENTRYPOINT(CMyTest1App)
ACED_ARXCOMMAND_ENTRY_AUTO(CMyTest1App,AdskMyTest,SyncVTR,ACRX_CMD_MODAL,NULL)
https://adndevblog.typepad.com/autocad/2014/07/synchronizing-model-space-viewports.html
解决方法
我找到了两个解决问题的应用,DWGsync(在 2021 年之前免费且兼容)https://apps.autodesk.com/ACD/es/Detail/Index?id=2788892389049910944&appLang=en&os=Win32_64 和 Drawing Sync(已获得许可且兼容的 autocad 2018)https://apps.autodesk.com/ACD/en/Detail/Index?id=2152736212918385179&appLang=en&os=Win32_64