转载:自定义浏览DWG控件的实现方法, 有时间研究一下(AcGsView使用)

转载来源:http://www.cnblogs.com/houlinbo/archive/2010/04/23/1718856.html

 

自定义浏览DWG控件的实现方法ARX 

 
总是需要在自定义控件上显示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);
}
}
}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值