在对话框中实现预览图形文件的功能

一、使用"acdbDisplayPreviewFromDwg"函数

1. 引用说明

/*
此功能获取由指定的图形的预览图像(如果有)pszDwgfilename,将其显示在由HWND参数pPreviewWnd标识的窗口中。图像尺寸最大变化不超过256 x 188像素。
如果pPreviewWnd窗口大于图像,则图像将被拉伸以适合图像。但是,如果窗口小于图像,则图像将不会被调整,并且会溢出到窗口的边界之外。
如果非空,pBgColor必须是代表RGB颜色的长整数。长格式是Windows SDK使用的格式颜色参考类型。
返回true表示成功;否则返回false。
*/

ACDB_PORT bool acdbDisplayPreviewFromDwg(
    const ACHAR * pszDwgfilename, 	// 输入路径文件名字符串
    void* pPreviewWnd, 	// 输入要在其中显示预览的窗口的HWND
    const Adesk::UInt32* pBgColor = nullptr	// 输入RGB颜色作为预览背景
);

2. 使用案例

 HWND pWnd;
 CFrameWnd *pFrame = (CFrameWnd*)GetDlgItem(IDC_PICTURE); 
 bool bResult = acdbDisplayPreviewFromDwg(_T("填入文件路径"), pFrame->m_hWnd);

二、结合AcGs库,重载静态文本,用以预览图形

1. 引用说明

  • AcGsManager::AcGsManager界面提供的服务有助于隐藏将AutoCAD和ARX应用程序连接到图形系统(GS)的详 细信息。每个AutoCAD
    AcDisplay对象都有一个AcGsManager。因此,AcGsManager对象与MDI客户端窗口以及AcDbDatabase对象具有一对一的关系。函数acgsGetGSManager()提供对AcGsManager对象的访问。
  • AcGsDeviceAcGsDevice是绘图表面的抽象,并封装了向其渲染图形的基础设备。 目前,AcGsDevice对应于GUI显示窗口。
    最终,将支持其他类型的设备(例如,硬拷贝,文件[.bmp,.wmf,.dwf]和剪贴板)。一个AcGsDevice拥有一个或多个AcGsView,并且必须管理损坏的区域并将更新委派给这些视图。
    此外,它还响应操作系统通知,例如图形系统(GS)客户端从基础设备转发的窗口大小更改。
  • AcGsView:AcGsView对象对应于GUI窗口的一部分,定义视图的一组相机参数以及要查看的对象的集合。更具体地说,AcGsView可用于表示AutoCAD视口。将AcGsView添加到AcGsDevice。一个视图一次只能属于一个设备。需要告知视图正在查看的内容。客户端添加和删除对应于指定模型的已查看部分的(AcGiDrawable,AcGsModel)对。每个AcGsView都有一个RenderMode,它对应于在该视图中绘制几何图形时采用的算法…
    AcGsView具有两种状态:交互式和非交互式。默认情况下,AcGsView是非交互式的。这意味着所有方法在调用时立即执行,仅在完成时返回。所有返回值都是可信赖的,并且可以调用所有方法。
  • AcGsModelAcGsModel类是数据库的抽象。 该数据库可以是AcDbDatabase,它可以是瞬时图形的容器(例如Icon和Grid),或者可以表示另一种持久数据库格式,例如DWF。
    最重要的是,AcGsModel为数据库提供了一种机制,可将更改(添加,删除和修改)通知图形系统(GS)。每个AcGsModel都有一个RenderType,它向GS提供有关如何渲染此模型的几何图形的提示。

2. 使用案例

#pragma once


/**
 * @brief		预览DWG图形的静态文本类
 */
class IMechGsPreviewCtrl : public CStatic
{
public:
	IMechGsPreviewCtrl();
	~IMechGsPreviewCtrl();

private:
	AcDbExtents		m_Extents;	/**< 图纸范围  */		
	AcGsView		*m_pView;	/**< 图形系统中的视图,用来绘制图形的区域 */		
	AcGsDevice		*m_pDevice;	/**< 图形系统中的设备 */		
	AcGsModel		*m_pModel;	/**< 临时数据库 */			
	AcDbDatabase	*m_pDb;		/**< 该预览空间绑定的数据库  */		

protected:
	/**
	 * @brief 绘制消息处理程序
	 */
	afx_msg void OnPaint();
	/**
	 * @brief 大小改变消息处理程序
	 */
	afx_msg void OnSize(UINT nType, int cx, int cy);
	DECLARE_MESSAGE_MAP()

public:
	/**
	 * @brief 传入DWG文件预览图形
	 *
	 * @param strFilePath 路径
	 */
	bool Init(const CString& strFilePath);

	/**
	 * @brief 传入数据库指针预览图形
	 *
	 * @param pDb 数据库指针
	 */
	bool Init(AcDbDatabase *pDb);

protected:
	/**
	 * @brief 缩放到图纸可见
	 */
	void ZoomWindow();

	/**
	 * @brief 清除
	 */
	void Clear();

	/**
	 * @brief 初始化图形系统
	 */
	void InitGS(/*HINSTANCE hRes*/);

	/**
	 * @brief 内部初始化
	 *
	 * @param pDb 数据库指针
	 */
	bool InitInner(AcDbDatabase *pDb);

	/**
	 * @brief 获得当前视口的信息
	 *
	 * @param dHeight 视口高度
	 * @param dWidth 视口宽度
	 * @param ptViewCenter 视口中心点
	 * @param vecViewDir 视口的观察向量
	 * @param dTwist 视口中视图的扭曲角度
	 * @return true/false
	 */
	bool GetActiveViewPortInfo(double& dHeight, double& dWidth, AcGePoint3d& ptViewCenter,
		AcGeVector3d& vecViewDir, double& dTwist, bool bViewCenter);

	/**
	 * @brief 获取块中所有实体Id
	 *
	 * @param pBlockTableRecord 块表记录
	 * @param EntIdArr 传出的实体集
	 */
	void GetAllEnt(AcDbBlockTableRecord *pBlockTableRecord, AcDbObjectIdArray& EntIdArr);

	/**
	 * @brief 获取实体包围盒
	 *
	 * @param EntId 实体Id
	 * @param Extents 传出的包围盒
	 */
	Acad::ErrorStatus GetEntExtents(const AcDbObjectId& EntId, AcDbExtents& Extents);

	/**
	 * @brief 获取实体集整体包围盒
	 *
	 * @param EntIdArr 实体集
	 * @param Extents 传出的包围盒
	 */
	void GetEntExtents(const AcDbObjectIdArray& EntIdArr, AcDbExtents& Extents);

	/**
	 * @brief 获取两点的中心点
	 *
	 * @param pt1 点1
	 * @param pt2 点2
	 * @param ptMid 传出的中心点
	 */
	void GetMidPoint(const AcGePoint3d& pt1, const AcGePoint3d& pt2, AcGePoint3d& ptMid);
};

#include "stdafx.h"
#include "resource.h"
#include "IMechGsPreviewCtrl.h"

IMechGsPreviewCtrl::IMechGsPreviewCtrl()
{
	m_pView = nullptr;			
	m_pDevice = nullptr;		
	m_pModel = nullptr;			
	m_pDb = nullptr;			
}

IMechGsPreviewCtrl::~IMechGsPreviewCtrl()
{
	Clear();
}


BEGIN_MESSAGE_MAP(IMechGsPreviewCtrl, CStatic)
	ON_WM_PAINT()
	ON_WM_SIZE()
END_MESSAGE_MAP()


void IMechGsPreviewCtrl::OnPaint()
{
	CPaintDC dc(this);
	if (m_pView)
	{
		m_pView->invalidate();
		m_pView->update();
	}
}

void IMechGsPreviewCtrl::OnSize(UINT nType, int cx, int cy)
{
	CRect rect;
	if (m_pDevice)
	{
		GetClientRect(&rect);
		m_pDevice->onSize(rect.Width(), rect.Height());
	}
}

void IMechGsPreviewCtrl::Clear()
{
	AcGsManager *pGsManager = acgsGetGsManager();
	ASSERT(pGsManager);
	if (m_pView)
	{
		m_pView->eraseAll();
		if (m_pDevice)
		{
			bool b = m_pDevice->erase(m_pView);
			ASSERT(b);
		}

		AcGsClassFactory *pFactory = pGsManager->getGSClassFactory();
		ASSERT(pFactory);

		pFactory->deleteView(m_pView);
		m_pView = nullptr;
	}

	if (m_pModel)
	{
		pGsManager->destroyAutoCADModel(m_pModel);
		m_pModel = nullptr;
	}

	if (m_pDevice)
	{
		pGsManager->destroyAutoCADDevice(m_pDevice);
		m_pDevice = nullptr;
	}

	if (m_pDb)
	{
		delete m_pDb;
		m_pDb = nullptr;
	}
}

bool IMechGsPreviewCtrl::Init(const CString& strFilePath)
{
	Clear();

	m_pDb = new AcDbDatabase(false, true);

	Acad::ErrorStatus es = m_pDb->readDwgFile(strFilePath);

	if (es != Acad::eOk)
	{
		delete m_pDb;
		m_pDb = NULL;
	}

	return InitInner(m_pDb);
}


bool IMechGsPreviewCtrl::Init(AcDbDatabase *pDb)
{
	Clear();

	return InitInner(pDb);
}


bool IMechGsPreviewCtrl::GetActiveViewPortInfo(double& dHeight, double& dWidth, AcGePoint3d& ptViewCenter,
	AcGeVector3d& vecViewDir, double& dTwist, bool bViewCenter)
{
	AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();
	if (pDb == NULL)
	{
		return false;
	}

	AcDbViewportTable *pVTable = NULL;
	Acad::ErrorStatus es = pDb->getViewportTable(pVTable, AcDb::kForRead);

	if (es == Acad::eOk)
	{
		AcDbViewportTableRecord *pViewPortRec = NULL;
		es = pVTable->getAt(_T("*Active"), pViewPortRec, AcDb::kForRead);
		if (es == Acad::eOk)
		{
			dHeight = pViewPortRec->height();
			dWidth = pViewPortRec->width();

			if (bViewCenter == true)
			{
				struct resbuf rb;
				memset(&rb, 0, sizeof(struct resbuf));
				acedGetVar(_T("VIEWCTR"), &rb);

				ptViewCenter = AcGePoint3d(rb.resval.rpoint[X], rb.resval.rpoint[Y], rb.resval.rpoint[Z]);
			}
			else
			{
				ptViewCenter = pViewPortRec->target();
			}

			vecViewDir = pViewPortRec->viewDirection();
			dTwist = pViewPortRec->viewTwist();
		}

		pVTable->close();
		pViewPortRec->close();
	}

	return (true);
}


void IMechGsPreviewCtrl::InitGS(/*HINSTANCE hRes*/)
{
	// 获取数据库的图形管理系统:函数acgsGetGSManager()提供对AcGsManager对象的访问
	AcGsManager *pGsManager = acgsGetGsManager();
	ASSERT(pGsManager);

	// 图形管理系统的基类
	AcGsClassFactory *pFactory = pGsManager->getGSClassFactory();
	ASSERT(pFactory);

	// 创建GUI显示窗口:使用指定的内核和窗口创建屏幕上的AcGsDevice
	m_pDevice = pGsManager->createAutoCADDevice(m_hWnd);
	ASSERT(m_pDevice);

	// 设置GUI显示大小
	CRect rect;
	GetClientRect(&rect);
	m_pDevice->onSize(rect.Width(), rect.Height());

	// 创建CAD视图:使用用于创建指定设备的相同内核创建一个AcGsView
	m_pView = pFactory->createView();
	ASSERT(m_pView);

	// 创建一个临时数据库
	m_pModel = pGsManager->createAutoCADModel();
	ASSERT(m_pModel);

	// 将视图绑定到GUI显示窗口
	m_pDevice->add(m_pView);

	double dHeight = 0.0, dWidth = 0.0, dTwist = 0.0;
	AcGePoint3d ptViewCenter;
	AcGeVector3d vecViewDir;
	GetActiveViewPortInfo(dHeight, dWidth, ptViewCenter, vecViewDir, dTwist, true);

	// 设置视图
	m_pView->setView(ptViewCenter + vecViewDir, ptViewCenter, AcGeVector3d(0.0, 1.0, 0.0), 1.0, 1.0);
}

bool IMechGsPreviewCtrl::InitInner(AcDbDatabase *pDb)
{
	if (pDb == nullptr)
	{
		m_pDb = new AcDbDatabase(true, true);
	}
	else
	{
		m_pDb = pDb;
	}

	if (m_pDb == nullptr)
	{
		return false;
	}

	Acad::ErrorStatus es = Acad::eOk;
	AcDbBlockTable *pBlockTable = nullptr;
	AcDbBlockTableRecord *pBlockTableRecord = NULL;

	if ((es = m_pDb->getBlockTable(pBlockTable, AcDb::kForRead)) != Acad::eOk)
	{
		return false;
	}

	if ((es = pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForRead)) != Acad::eOk)
	{
		pBlockTableRecord->close();
		return false;
	}

	pBlockTable->close();

	AcDbObjectIdArray EntIdArr;
	GetAllEnt(pBlockTableRecord, EntIdArr);

	// 获取图纸中实体的最小包围盒
	GetEntExtents(EntIdArr, m_Extents);
	InitGS();

	// 指定视图可以查看临时数据库中的模型空间块
	m_pView->add(pBlockTableRecord, m_pModel);
	pBlockTableRecord->close();

	// 缩放窗口
	ZoomWindow();

	return TRUE;
}


void IMechGsPreviewCtrl::ZoomWindow()
{
	AcGePoint3d ptViewCenter;
	GetMidPoint(m_Extents.maxPoint(), m_Extents.minPoint(), ptViewCenter);

	double dLenght = m_Extents.maxPoint().x - m_Extents.minPoint().x;
	double dWidth = m_Extents.maxPoint().y - m_Extents.minPoint().y;

	m_pView->setView(ptViewCenter + AcGeVector3d::kZAxis, ptViewCenter, AcGeVector3d::kYAxis, dLenght * 1.05, dWidth * 1.05);

	OnPaint();
}


void IMechGsPreviewCtrl::GetMidPoint(const AcGePoint3d& pt1, const AcGePoint3d& pt2, AcGePoint3d& ptMid)
{
	ptMid.x = 0.5 *(pt1.x + pt2.x);
	ptMid.y = 0.5 *(pt1.y + pt2.y);
	ptMid.z = 0.5 *(pt1.z + pt2.z);
}


void IMechGsPreviewCtrl::GetAllEnt(AcDbBlockTableRecord *pBlockTableRecord, AcDbObjectIdArray& EntIdArr)
{
	EntIdArr.setPhysicalLength(0);

	AcDbBlockTableRecordIterator *pIter = nullptr;
	if (pBlockTableRecord->newIterator(pIter) == Acad::eOk)
	{
		for (pIter->start(); !pIter->done(); pIter->step())
		{
			AcDbObjectId EntId;
			if (Acad::eOk == pIter->getEntityId(EntId))
			{
				EntIdArr.append(EntId);
			}
		}

		delete pIter;
		pIter = nullptr;
	}

	return;
}


Acad::ErrorStatus IMechGsPreviewCtrl::GetEntExtents(const AcDbObjectId& EntId, AcDbExtents& Extents)
{
	Acad::ErrorStatus es;
	AcDbEntityPointer pEntity(EntId, AcDb::kForRead);
	if (pEntity.openStatus() == Acad::eOk)
	{
		AcDbBlockReference *pBlkRef = AcDbBlockReference::cast(pEntity);
		if (pBlkRef)
		{
			es = pBlkRef->geomExtentsBestFit(Extents);
		}
		else
		{
			es = pEntity->getGeomExtents(Extents);
		}
	}

	return (es);
}


void IMechGsPreviewCtrl::GetEntExtents(const AcDbObjectIdArray& EntIdArr, AcDbExtents& Extents)
{
	for (int i = 0; i < EntIdArr.length(); i++)
	{
		AcDbExtents ExtentsTemp;
		if (GetEntExtents(EntIdArr[i], ExtentsTemp) == Acad::eOk)
		{
			Extents.addExt(ExtentsTemp);
		}
	}
}
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值