admin 发表于 2024-9-20 15:17:00

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

一、使用"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对象的访问。
AcGsDevice:AcGsDevice是绘图表面的抽象,并封装了向其渲染图形的基础设备。 目前,AcGsDevice对应于GUI显示窗口。
最终,将支持其他类型的设备(例如,硬拷贝,文件[.bmp,.wmf,.dwf]和剪贴板)。一个AcGsDevice拥有一个或多个AcGsView,并且必须管理损坏的区域并将更新委派给这些视图。
此外,它还响应操作系统通知,例如图形系统(GS)客户端从基础设备转发的窗口大小更改。
AcGsView:AcGsView对象对应于GUI窗口的一部分,定义视图的一组相机参数以及要查看的对象的集合。更具体地说,AcGsView可用于表示AutoCAD视口。将AcGsView添加到AcGsDevice。一个视图一次只能属于一个设备。需要告知视图正在查看的内容。客户端添加和删除对应于指定模型的已查看部分的(AcGiDrawable,AcGsModel)对。每个AcGsView都有一个RenderMode,它对应于在该视图中绘制几何图形时采用的算法…
AcGsView具有两种状态:交互式和非交互式。默认情况下,AcGsView是非交互式的。这意味着所有方法在调用时立即执行,仅在完成时返回。所有返回值都是可信赖的,并且可以调用所有方法。
AcGsModel:AcGsModel类是数据库的抽象。 该数据库可以是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, rb.resval.rpoint, rb.resval.rpoint);
                        }
                        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, ExtentsTemp) == Acad::eOk)
                {
                        Extents.addExt(ExtentsTemp);
                }
        }
}
页: [1]
查看完整版本: 在对话框中实现预览图形文件的功能