- 积分
- 24557
- 明经币
- 个
- 注册时间
- 2004-3-17
- 在线时间
- 小时
- 威望
-
- 金钱
- 个
- 贡献
-
- 激情
-
|
发表于 2009-5-15 21:51:00
|
显示全部楼层
本帖最后由 作者 于 2009-5-16 9:37:03 编辑
这几天收集Kean的专题,无意间发现了这个:
AutoCAD .NET version of the ObjectARX BlockView sample这里有个ObjectArx的解决方案,参考一下吧
总是需要在自定义控件上显示DWG图形,如在一个对话框上动态浏览一个DWG图形,于是写了一个控件,专门用来动态浏览DWG,这个控件从CStatic中派生,运用AcGs类库中的AcGsView,AcGsDevice,AcGsModel来协作显示DWG图形。
从CStatic派生,使用方便,只要在对话框中放一个CStatic,然后把CStatic的对象名换成fcGsPreviewCtrl即可。- fcGsPreviewCtrl.h
- /********************************************************************
- 日 期: 2007/10/08
- 文件 名: fcgspreviewctrl.h
- 作 者: Racky Ye
- 单 位:
- 描 述: 用来预览DWG图形的控件
- *********************************************************************/
- #ifndef _FC_GS_PREVIEW_CTRL_H__
- #define _FC_GS_PREVIEW_CTRL_H__
- #if _MSC_VER > 1000
- #pragma once
- #endif // _MSC_VER > 1000
- #include "acgi.h"
- #include <math.h>
- #include "gs.h"
- #include "acgs.h"
- #include "acgsmanager.h"
- // 用来预览DWG图形的控件
- class fcGsPreviewCtrl : public CStatic
- {
- public:
- fcGsPreviewCtrl();
- virtual ~fcGsPreviewCtrl();
- public:
- //函数功能:传入dwg文件即可预览
- BOOL Init(LPCTSTR szDwgFile);
- //函数功能:传入数据库指针即可预览数据库中的实体
- BOOL Init(AcDbDatabase *pDb);
- // 缩放到整个图纸可见
- void ZoomE();
- void Clear();
- protected:
- void InitGS(HINSTANCE hRes); // 初始化图形系统
- BOOL InitInner(AcDbDatabase *pDb); // 内部初始化
- bool GetActiveViewPortInfo (ads_real &height, ads_real &width, AcGePoint3d &target,
- AcGeVector3d &viewDir, ads_real &viewTwist, bool getViewCenter);
- //获得块中的所有实体
- void GetAllEnt(const AcDbObjectId& idBlockRec, AcDbObjectIdArray& IDArray);
- //获得实体的范围
- Acad::ErrorStatus GetEntExtents(const AcDbObjectId& idEnt, AcDbExtents& extents);
- void GetEntExtents(const AcDbObjectIdArray& aridEnt, AcDbExtents& extents);
- void Mid(const AcGePoint3d& pt1, const AcGePoint3d& pt2, AcGePoint3d& ptMid);
- protected:
- //{{AFX_MSG(fcGsPreviewCtrl)
- afx_msg void OnPaint();
- afx_msg void OnSize(UINT nType, int cx, int cy);
- afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
- afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
- afx_msg void OnMButtonDown(UINT nFlags, CPoint point);
- afx_msg void OnMButtonUp(UINT nFlags, CPoint point);
- afx_msg void OnMouseMove(UINT nFlags, CPoint point);
- afx_msg UINT OnNcHitTest(CPoint point);
- afx_msg void OnSetFocus(CWnd* pOldWnd);
- afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
- private:
- AcDbExtents m_extents; // 图纸范围
- HCURSOR m_hPanCursor; // 移动时的图标
- HCURSOR m_hCrossCursor; // 十字图标
- HCURSOR m_hOrbitCursor; // 旋转图标
- AcGsView *m_pView; // 图形系统中的视图,用来绘制图形的区域
- AcGsDevice *m_pDevice; // 图形系统中的设备,
- AcGsModel *m_pModel;
- bool m_bPanning; // 是否处于移动图形状态
- bool m_bOrbiting; // 是否处于旋转图形状态
- AcDbDatabase* m_pDb; // 该预览空间绑定的数据库
- CPoint m_StartPt; // 移动或旋转时的起点
- };
- /////////////////////////////////////////////////////////////////////////////
- //{{AFX_INSERT_LOCATION}}
- // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
- #endif // !defined(_FC_GS_PREVIEW_CTRL_H__)
- CPP文件:
- /********************************************************************
- 日 期: 2007/10/08
- 文件 名: fcgspreviewctrl.cpp
- 作 者: Racky Ye
- 单 位:
- 描 述: 用来预览DWG图形的控件
- *********************************************************************/
- #include "StdAfx.h"
- #include "resource.h"
- #include "fcGsPreviewCtrl.h"
- #include "dbents.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- fcGsPreviewCtrl::fcGsPreviewCtrl()
- {
- m_hPanCursor = NULL; // 移动时的图标
- m_hCrossCursor = NULL; // 十字图标
- m_hOrbitCursor = NULL; // 旋转图标
- m_pView = NULL; // 图形系统中的视图,用来绘制图形的区域
- m_pDevice = NULL; // 图形系统中的设备,
- m_pModel = NULL;
- m_bPanning = false; // 是否处于移动图形状态
- m_bOrbiting = false; // 是否处于旋转图形状态
- m_pDb = NULL; // 该预览空间绑定的数据库
- }
- fcGsPreviewCtrl::~fcGsPreviewCtrl()
- {
- Clear();
- }
- BEGIN_MESSAGE_MAP(fcGsPreviewCtrl, CStatic)
- //{{AFX_MSG_MAP(fcGsPreviewCtrl)
- ON_WM_PAINT()
- ON_WM_SIZE()
- ON_WM_MOUSEWHEEL()
- ON_WM_LBUTTONDOWN()
- ON_WM_MBUTTONDOWN()
- ON_WM_MBUTTONUP()
- ON_WM_MOUSEMOVE()
- ON_WM_NCHITTEST()
- ON_WM_SETFOCUS()
- ON_WM_LBUTTONUP()
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // fcGsPreviewCtrl message handlers
- void fcGsPreviewCtrl::OnPaint()
- {
- CPaintDC dc(this);
- //刷新图形系统视图
- if (m_pView)
- {
- m_pView->invalidate();
- m_pView->update();
- }
- }
- void fcGsPreviewCtrl::OnSize(UINT nType, int cx, int cy)
- {
- CRect rect;
- if (m_pDevice)
- {
- GetClientRect(&rect);
- m_pDevice->onSize(rect.Width(), rect.Height());
- }
- }
- BOOL fcGsPreviewCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
- {
- if (m_pView)
- {
- if (zDelta < 0)
- m_pView->zoom(0.5);
- else
- m_pView->zoom(1.5);
- Invalidate();
- }
- return TRUE;
- }
- void fcGsPreviewCtrl::OnLButtonDown(UINT nFlags, CPoint point)
- {
- SetFocus();
- //设置光标样式
- m_bOrbiting = true;
- SetCapture();
- ::SetClassLong(m_hWnd, GCL_HCURSOR, NULL);
- ::SetCursor(m_hOrbitCursor);
- m_StartPt = point;
- }
- void fcGsPreviewCtrl::OnMButtonDown(UINT nFlags, CPoint point)
- {
- //开始移动
- m_bPanning = true;
- SetCapture();
- ::SetClassLong(m_hWnd,GCL_HCURSOR,NULL);
- ::SetCursor(m_hPanCursor);
- m_StartPt = point;
- }
- void fcGsPreviewCtrl::OnMButtonUp(UINT nFlags, CPoint point)
- {
- ReleaseCapture();
- m_bPanning = false;
- ::SetClassLong(m_hWnd,GCL_HCURSOR,(long)m_hCrossCursor);
- }
- //函数功能:鼠标滚轮放大缩小视图
- void fcGsPreviewCtrl::OnMouseMove(UINT nFlags, CPoint point)
- {
- if (m_pView)
- {
- if (m_bPanning)
- {
- //完成从设备坐标系统到世界坐标系统的转换
- AcGeVector3d pan_vec(-(point.x-m_StartPt.x),point.y-m_StartPt.y,0);
- pan_vec.transformBy(m_pView->viewingMatrix() * m_pView->worldToDeviceMatrix().inverse());
- m_pView->dolly(pan_vec);
- Invalidate();
- m_StartPt = point;
- }
- else if (m_bOrbiting)
- {
- const double Half_Pi = 1.570796326795;
- AcGsDCRect view_rect;
- m_pView->getViewport (view_rect);
- int nViewportX = (view_rect.m_max.x - view_rect.m_min.x) + 1;
- int nViewportY = (view_rect.m_max.y - view_rect.m_min.y) + 1;
- int centerX = int(nViewportX / 2.0f) + view_rect.m_min.x;
- int centerY = int(nViewportY / 2.0f) + view_rect.m_min.y;
- const double radius = min (nViewportX, nViewportY) * 0.4f;
- // 从最后和新的鼠标位置计算出两个矢量
- AcGeVector3d last_vector ((m_StartPt.x - centerX) / radius,
- -(m_StartPt.y - centerY) / radius,
- 0.0);
- if (last_vector.lengthSqrd () > 1.0) // 超出半径范围
- last_vector.normalize ();
- else
- last_vector.z = sqrt (1.0 - last_vector.x * last_vector.x - last_vector.y * last_vector.y);
- AcGeVector3d new_vector((point.x - centerX) / radius,
- -(point.y - centerY) / radius,
- 0.0);
- if (new_vector.lengthSqrd () > 1.0) // 超出半径范围
- new_vector.normalize ();
- else
- new_vector.z = sqrt (1.0 - new_vector.x * new_vector.x - new_vector.y * new_vector.y);
- // 确定相机操作的角度
- AcGeVector3d rotation_vector (last_vector);
- rotation_vector = rotation_vector.crossProduct (new_vector); // rotation_vector = last_vector x new_vector
- AcGeVector3d work_vector (rotation_vector);
- work_vector.z = 0.0f; // rotation_vector到xy平面的投影
- double roll_angle = atan2 (work_vector.x, work_vector.y); // 假设相机的向上矢量是朝上的
- // 计算向上的矢量和工作矢量的夹角
- double length = rotation_vector.length ();
- double orbit_y_angle = (length != 0.0) ? acos (rotation_vector.z / length) + Half_Pi : Half_Pi; // represents inverse cosine of the dot product of the
- if (length > 1.0f)
- length = 1.0f;
- double rotation_angle = asin (length);
- // view操作
- m_pView->roll( roll_angle);
- m_pView->orbit( 0.0f, orbit_y_angle);
- m_pView->orbit( rotation_angle, 0.0f);
- m_pView->orbit( 0.0f, -orbit_y_angle);
- m_pView->roll(-roll_angle);
- Invalidate();
- m_StartPt = point;
- }
- else
- {
- ::SetClassLong(m_hWnd,GCL_HCURSOR,(long)m_hCrossCursor);
- SetFocus();
- }
- }
- }
- UINT fcGsPreviewCtrl::OnNcHitTest(CPoint point)
- {
- return HTCLIENT;
- }
- void fcGsPreviewCtrl::OnSetFocus(CWnd* pOldWnd)
- {
- ::SetClassLong(m_hWnd, GCL_HCURSOR, (long)m_hCrossCursor);
- }
- void fcGsPreviewCtrl::OnLButtonUp(UINT nFlags, CPoint point)
- {
- m_bOrbiting = false;
- ::SetClassLong(m_hWnd,GCL_HCURSOR,(long)m_hCrossCursor);
- ReleaseCapture();
- }
- void fcGsPreviewCtrl::Clear()
- {
- AcGsManager *pGsManager = acgsGetGsManager();
- RXASSERT(pGsManager);
- if (m_pView)
- {
- m_pView->eraseAll();
- if (m_pDevice)
- {
- bool b = m_pDevice->erase(m_pView);
- RXASSERT(b);
- }
- AcGsClassFactory *pFactory = pGsManager->getGSClassFactory();
- RXASSERT(pFactory);
- pFactory->deleteView(m_pView);
- m_pView = NULL;
- }
- if (m_pModel)
- {
- pGsManager->destroyAutoCADModel(m_pModel);
- m_pModel = NULL;
- }
- if (m_pDevice)
- {
- pGsManager->destroyAutoCADDevice(m_pDevice);
- m_pDevice = NULL;
- }
- if (m_pDb)
- {
- delete m_pDb;
- m_pDb = NULL;
- }
- }
- //函数功能:传入dwg文件即可预览
- BOOL fcGsPreviewCtrl::Init(LPCTSTR szDwgFile)
- {
- Clear();
- m_pDb = new AcDbDatabase(false,true);
- Acad::ErrorStatus es = m_pDb->readDwgFile(szDwgFile);
- if (es != Acad::eOk)
- {
- delete m_pDb;
- m_pDb = NULL;
- }
- return InitInner(m_pDb);
- }
- //函数功能:传入数据库指针即可预览数据库中的实体
- BOOL fcGsPreviewCtrl::Init(AcDbDatabase *pDb)
- {
- Clear();
- return InitInner(pDb);
- }
- //函数功能:获得当前视口的信息。
- //输出参数:height 视口高度,width 视口宽度,target 视口中心点,viewDir 视口的观察向量,twist 扭曲的视口
- bool fcGsPreviewCtrl::GetActiveViewPortInfo (ads_real &height, ads_real &width,
- AcGePoint3d &target, AcGeVector3d &viewDir,
- ads_real &viewTwist, bool getViewCenter)
- {
- 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 ("*Active", pViewPortRec, AcDb::kForRead);
- if (es == Acad::eOk)
- {
- height = pViewPortRec->height ();
- width = pViewPortRec->width ();
- if (getViewCenter == true)
- {
- struct resbuf rb;
- memset (&rb, 0, sizeof (struct resbuf));
- acedGetVar ("VIEWCTR", &rb);
- target = AcGePoint3d (rb.resval.rpoint[X], rb.resval.rpoint[Y], rb.resval.rpoint[Z]);
- }
- else
- {
- target = pViewPortRec->target ();
- }
- viewDir = pViewPortRec->viewDirection ();
- viewTwist = pViewPortRec->viewTwist ();
- }
- pVTable->close ();
- pViewPortRec->close();
- }
- return (true);
- }
- //函数功能:初始化图形系统
- void fcGsPreviewCtrl::InitGS(HINSTANCE hRes)
- {
- // 加载光标
- if (m_hPanCursor == NULL)
- m_hPanCursor = LoadCursor(hRes,MAKEINTRESOURCE(IDI_PAN));
- if (m_hCrossCursor == NULL)
- m_hCrossCursor = LoadCursor(hRes,MAKEINTRESOURCE(IDI_CROSS));
- if (m_hOrbitCursor == NULL)
- m_hOrbitCursor = LoadCursor(hRes,MAKEINTRESOURCE(IDI_ORBIT));
- ::SetClassLong(m_hWnd,GCL_HCURSOR,NULL);
- // 初始化视图
- // 获得图形系统管理器
- AcGsManager *pGsManager = acgsGetGsManager();
- RXASSERT(pGsManager);
- // 获得图形系统类工厂
- AcGsClassFactory *pFactory = pGsManager->getGSClassFactory();
- RXASSERT(pFactory);
- // 创建图形系统设备
- m_pDevice = pGsManager->createAutoCADDevice(m_hWnd);
- RXASSERT(m_pDevice);
- CRect rect;
- GetClientRect(&rect);
- m_pDevice->onSize(rect.Width(), rect.Height());
- // 创建图形系统视图
- m_pView = pFactory->createView();
- RXASSERT(m_pView);
- m_pModel = pGsManager->createAutoCADModel();
- RXASSERT(m_pModel);
- m_pDevice->add(m_pView);
- double height = 0.0, width = 0.0, viewTwist = 0.0;
- AcGePoint3d ptTargetView;
- AcGeVector3d vecViewDir;
- GetActiveViewPortInfo (height, width, ptTargetView, vecViewDir, viewTwist, true);
- m_pView->setView(ptTargetView + vecViewDir, ptTargetView,
- AcGeVector3d(0.0, 1.0, 0.0), 1.0, 1.0);
- }
- BOOL fcGsPreviewCtrl::InitInner(AcDbDatabase *pDb)
- {
- if (pDb == NULL)
- {
- m_pDb = new AcDbDatabase(true, true);
- }
- else
- {
- m_pDb = pDb;
- }
- if (m_pDb == NULL)
- return FALSE;
- Acad::ErrorStatus es = Acad::eOk;
- AcDbBlockTableRecord *pRec = NULL;
- AcDbBlockTable *pTab = NULL;
- if ((es = m_pDb->getBlockTable(pTab, AcDb::kForRead))!=Acad::eOk)
- return FALSE;
- if ((es = pTab->getAt(ACDB_MODEL_SPACE,pRec,AcDb::kForRead))!=Acad::eOk)
- {
- pTab->close();
- return FALSE;
- }
- pTab->close();
- AcDbObjectId idRec = pRec->id();
- AcDbObjectIdArray aridEnt;
- GetAllEnt(idRec, aridEnt);
- GetEntExtents(aridEnt, m_extents);
- InitGS(_hdllInstance);
- m_pView->add(pRec, m_pModel);
- pRec->close();
- ZoomE();
- return TRUE;
- }
- // 缩放到整个图纸可见
- void fcGsPreviewCtrl::ZoomE()
- {
- AcGePoint3d ptTargetView;
- Mid(m_extents.maxPoint(), m_extents.minPoint(), ptTargetView);
- double dLenght = m_extents.maxPoint().x - m_extents.minPoint().x;
- double dWidth = m_extents.maxPoint().y - m_extents.minPoint().y;
- m_pView->setView(ptTargetView + AcGeVector3d::kZAxis,ptTargetView,AcGeVector3d::kYAxis,dLenght*1.05,dWidth*1.05);
- OnPaint();
- }
- void fcGsPreviewCtrl::Mid(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 fcGsPreviewCtrl::GetAllEnt(const AcDbObjectId& idBlockRec, AcDbObjectIdArray& IDArray)
- {
- IDArray.setPhysicalLength(0);
- Acad::ErrorStatus es;
- AcDbBlockTableRecord *pBlkRec = NULL;
- if (Acad::eOk != (es = acdbOpenObject(pBlkRec,idBlockRec,AcDb::kForRead)))
- {
- return;
- }
- AcDbBlockTableRecordIterator *pIt = NULL;
- pBlkRec->newIterator(pIt);
- pBlkRec->close();
- for (pIt->start(); !pIt->done(); pIt->step())
- {
- AcDbObjectId idEnt;
- if (Acad::eOk == pIt->getEntityId(idEnt))
- {
- IDArray.append(idEnt);
- }
- }
- delete pIt;
- pIt = NULL;
- }
- //函数功能:获得实体的范围
- Acad::ErrorStatus fcGsPreviewCtrl::GetEntExtents(const AcDbObjectId& idEnt, AcDbExtents& extents)
- {
- Acad::ErrorStatus es;
- AcDbEntity *pEnt = NULL;
- if (Acad::eOk == acdbOpenObject(pEnt, idEnt, AcDb::kForRead))
- {
- AcDbBlockReference *pBlkRef = AcDbBlockReference::cast(pEnt);
- if (pBlkRef)
- {
- es = pBlkRef->geomExtentsBestFit(extents);
- }
- else
- {
- es = pEnt->getGeomExtents(extents);
- }
- pEnt->close();
- }
- return (es);
- }
- void fcGsPreviewCtrl::GetEntExtents(const AcDbObjectIdArray& aridEnt, AcDbExtents& extents)
- {
- for (int i = 0; i<aridEnt.length();i++)
- {
- AcDbExtents tem;
- if (GetEntExtents(aridEnt[i], tem) == Acad::eOk)
- {
- extents.addExt(tem);
- }
- }
- }
|
|