// fcGsPreviewCtrl.cpp : 实现文件
//
#include "StdAfx.h"
#include "resource.h"
#include "fcGsPreviewCtrl.h"
#include "dbents.h"
#include "dbapserv.h"
#include "dbxentrypoint.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define RXASSERT ASSERT
IMPLEMENT_DYNAMIC(fcGsPreviewCtrl, CStatic)
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();
自定义浏览DWG控件的实现方法
4星 · 超过85%的资源 需积分: 10 97 浏览量
2013-08-01
15:15:58
上传
评论 2
收藏 543KB RAR 举报
天外孤寂
- 粉丝: 8
- 资源: 9