原理:Visual C++空间图形可视化算法原理与实践
图形拖拽思路
拖拽常用于在图形的定位和组合是需要交互式移动的情况。其思路就是确定图形的新旧定位点,以此来绘制拖拽路径(类似于橡皮筋的实现),鼠标移动过程中不断擦除旧图形显示新图形。
图形拖拽步骤
1、拖拽的前提是b_select为真,即图形被选中。确定图形的定位点newpt1,并根据鼠标移动的距离计算新的定位点newpt2,以便于绘制拖拽路径.
2、计算拖拽过程中外接矩形的左上角点和右下角点,存储在TopLeftNew、BottomRightNew中。
3、用拖动后的新坐标绘制图形。
添加鼠标消息
draftView.h
class CDraftView : public CView
{
protected: // create from serialization only
CDraftView();
DECLARE_DYNCREATE(CDraftView)
// Attributes
public:
CDraftDoc* GetDocument();
//圆所在的矩形区域,圆心旧坐标,新坐标
CPoint TopLeft, BottomRight, newpt1, newpt2;
CPoint TopLeftNew, BottomRightNew; //新的圆所在矩形区域
CPoint start, end;
BOOL b_select; //是否选中了圆
void translate(CPoint &to, CPoint &from, CPoint &start, CPoint &end); //移动一定距离
void translate(CPoint &pt, CPoint &start, CPoint &end); //移动一定距离
// Operations
public:
BOOL select(CPoint &pt, CPoint &topLeft, CPoint &rightBottom); //选圆
drawView.cpp
CDraftView::CDraftView()
{
// TODO: add construction code here
TopLeftNew = TopLeft = CPoint(50, 50); //左上角点
BottomRightNew = BottomRight = CPoint(150, 150); //右下角点
newpt1 = CPoint(100, 100); //圆心
b_select = FALSE;
}
void CDraftView::OnDraw(CDC* pDC)
{
CDraftDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
if(b_select) //如果选中,加粗显示
{
CPen newPen(PS_SOLID, 2, RGB(0, 0, 0)), *oldPen;
oldPen = pDC->SelectObject(&newPen);
pDC->Ellipse(TopLeft.x, TopLeft.y, BottomRight.x, BottomRight.y); //绘制对象圆
pDC->SelectObject(oldPen);
}
else
{
CPen newPen(PS_SOLID, 1, RGB(0, 0, 0)), *oldPen;
oldPen = pDC->SelectObject(&newPen);
pDC->Ellipse(TopLeft.x, TopLeft.y, BottomRight.x, BottomRight.y); //绘制对象圆
pDC->SelectObject(oldPen);
}
}
//如果鼠标点距圆的外界举行各边的距离小于10,就可以认为被选中
BOOL CDraftView::select(CPoint &pt, CPoint &topLeft, CPoint &bottomRight)
{
int x1 = topLeft.x;
int x2 = bottomRight.x;
int y1 = topLeft.y;
int y2 = bottomRight.y;
if( ( abs(pt.x - x1) < 10 && pt.y > y1 && pt.y < y2 ) ||
( abs(pt.x - x2) < 100 && pt.y > y1 && pt.y < y2 ) ||
( abs(pt.y - y1) < 10 && pt.x > x1 && pt.x < x2 ) ||
( abs(pt.y - y2) < 100 && pt.x > x1 && pt.x < x2 ) )
return TRUE;
else
return FALSE;
}
//将点平移一定距离
void CDraftView::translate(CPoint &to, CPoint &from, CPoint &start, CPoint &end)
{
to.x = from.x + end.x - start.x;
to.y = from.y + end.y - start.y;
}
//将点平移一定距离
void CDraftView::translate(CPoint &pt, CPoint &start, CPoint &end)
{
pt.x += end.x - start.x;
pt.y += end.y - start.y;
}
void CDraftView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
b_select = select(point, TopLeftNew, BottomRightNew); //拾取计算判断
start = end = point;
Invalidate();
CView::OnLButtonDown(nFlags, point);
}
void CDraftView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CDC *pdc = GetDC(); //获取设备环境
if(nFlags == MK_LBUTTON && b_select) //如果在鼠标按下和选中的情况下
{
pdc->SetROP2(R2_NOT); //拖拽图形的橡皮筋的实现
pdc->SelectStockObject(NULL_BRUSH); //空画刷不填充
//平移
CPoint pt1, pt2;
translate(pt1, TopLeft, start, end);
translate(pt2, BottomRight, start, end);
pdc->Ellipse(pt1.x, pt1.y, pt2.x, pt2.y);
translate(TopLeftNew, TopLeft, start, point);
translate(BottomRightNew, BottomRight, start, point);
pdc->Ellipse(TopLeftNew.x, TopLeftNew.y, BottomRightNew.x, BottomRightNew.y);
//拖拽线橡皮筋的实现
pdc->SetROP2(R2_NOT);
translate(pt1, newpt1, start, end);
pdc->MoveTo(newpt1);
pdc->LineTo(pt1);
translate(newpt2, newpt1, start, point);
pdc->MoveTo(newpt1);
pdc->LineTo(newpt2);
end = point;
}
CView::OnMouseMove(nFlags, point);
}
void CDraftView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
translate(newpt1, start, point); //圆心移到新的坐标
translate(TopLeft, start, point); //平移外接矩形顶点
translate(BottomRight, start, point);
Invalidate();
CView::OnLButtonUp(nFlags, point);
}
选中:
拖拽: